Python for .NETの動作を各環境でチェックする

Python for .NETは各種の環境へインストールが可能となっていますが、どの組み合わせで可能なのか今一歩情報がまとまっていません。
やってみて出来たものを中心にまとめていこうと思います。
できたものから順に記述していこうと思います。

あ、使い方はPython -> .NET方向の呼び出しのみで、Embedded Scripting(.NET -> Python)は使っていません。

# 共通項目

環境ごとにチェックしていますが、共通事項をここに書いておきます。

## Pythonnetのインストール

本家に[インストールガイド](https://github.com/pythonnet/pythonnet/wiki/Installation)があります。

###PyPI

```
pip install pythonnet
```
PyPIリポジトリはこちら：  https://pypi.python.org/pypi/pythonnet. Windows用のWheelもここにあります。

### Anaconda

```
conda install -c pythonnet pythonnet
```

```
conda install -c conda-forge pythonnet
```

Anacondaリポジトリはこちら：　https://anaconda.org/pythonnet/pythonnet

### github

```
pip install git+https://github.com/pythonnet/pythonnet
```
または、

```
git clone https://github.com/pythonnet/pythonnet
pip install .
```

### nuget

```
PM> Install-Package pythonnet -Version 3.0.0-preview2021-10-05
```

こちらにNuGetリポジトリがあります　https://www.nuget.org/packages/pythonnet/


# Windows 10

これを使うのは、Windows 10での動作がメインと思いますので、厚めに試します。

固定条件として以下とします。

* pythonnet 最新版 (2.4.0)
* Anaconda python 3.x

[Python.NET @ github](https://github.com/pythonnet/pythonnet)

には、以下のように書いてあるので、基本的に、3.7を使っています。

> Python 3.8.0 support
> Some features are disabled in Python 3.8.0 because of this bug in Python. The error is System.EntryPointNotFoundException : Unable to find an entry point named 'Py_CompileString' in DLL 'python38'. This will be fixed in Python 3.8.1.


## .NET Framework 4　（成功）

早く.NET5が出てほしいところですが、もうしばらく待たないといけないので、レガシーの方から。Windows10にプリインストールの.NET 4.6を利用しています。

### .NET環境の準備

特に何もしなくてよさそうです。標準の環境ですから当たりまえですね。

### Python環境の準備

これもAnaconda3の環境を入れただけで、特にTweakは必要なかったです。
やり方は共通項目参照。

### 動作確認

これでエラーが出なければ、ひとまず大丈夫でしょう。

``` Python
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form
```

``` Python
import sys
print("OS : ", Environment.OSVersion.VersionString)
print("Python : " ,sys.version)
print(".NET : ", Environment.Version.ToString())
print("pythonnet : " , clr.__version__)
```

``` :実行結果
OS :  Microsoft Windows NT 10.0.19041.0
python :  3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)]
.NET :  4.0.30319.42000
pythonnet :  2.4.0
```

Windows 10のバージョンが怪しいですが、そこは。。。

### .NET Standard ライブラリの呼び出し (成功)

BayesServerの最新版8.xから、[.NET Standardでの提供になった](https://www.bayesserver.com/ReleaseList.aspx)ことがあり、Python for .NET(.NET Framework) ->.NET Standardライブラリの呼び出しを検証しました。

``` Python
sys.path.append("C:/Program Files/Bayes Server/Bayes Server 8.16/API/DotNet/Standard20/")
clr.AddReference("BayesServer")
import BayesServer
network = Network()
network.Load("model.bayes")
print(network.Links.Count)
```

## .NET Core

デスクトップ開発者もそろそろ .NET Coreに移行を考えてもいいんじゃないかというレベルに来ているのかどうか知りませんが、.NET Core 3.1でFrameworkに劣らない機能が利用できるようになっています。
しかし、残念ながらpythonnetではまだ準備ができておらず、.NET CoreからPythonを動かそうという事はできないようです。（そもそも、そんな事許されるわけないじゃん）

[Support for .NET Core? #243 @ github](https://github.com/pythonnet/pythonnet/issues/243)

> .NET Core (CoreCLR) does not provide reverse pinvoke like .NET Framework on
Windows, neither C++/CLI. Hence the only way to get this working is to
embed .NET Core using C-API, like this is done for Mono. The problem is
that C-API for CoreCLR looks quite different from Mono.

CoreCLRではreverse P/Invokeがサポートされていないから、無理ゲーと書いています。
Pythonから.NET Coreは出来てもいいんじゃない？と思いますが。

しかし！上記は2016年の情報で、そこから以下のissueに状況が記されています。

[.NET Core support and CoreCLR embedding - cross-platform API #96 @ github](https://github.com/pythonnet/pythonnet/issues/96)

denfromufa commented on Oct 17, 2018 
によると、以下のサポート状況のようです。

| Platform       |       .NET-> Python	 |    Python -> .NET|
|:-----------------|------------------:|:------------------:|
| Windows             |   Tested |        Coded (npython.exe)|
| Linux |            Tested |      Tested (npython.exe)|
| OSX             |     Coded|        Coded (npython.exe)|

Pythonから.NET Coreを呼ぶ場合は、npython限定など、かなり制限がきついようですね。

# Linux

Linux上ではMonoを対象としたブリッジとして作動します。

## Mono-Amazon Linux

Sagemakerで使おうとして、普通にpipやcondaではインストールがうまくいかなかったのですが、どうやら以下でうまくいくようです。

```
source activate python3
conda install -c conda-forge/label/cf202003 pythonnet
```

Sagemakerのノートブックインスタンスでデフォルトで使われるEC2インスタンスは、以下が割り当てられます。

OS : Amazon Linux AMI release 2018.03 64bit
Conda : 4.8.4
Python : 3.6.13

最近Amazon Linux 2というのが出たようですが、まだデフォルトになっていないようです。
OS : Amazon Linux release 2 (Karoo) 64bit
Conda : 4.8.4
Python : 3.6.13

基本的にAL1,AL2とも同じ挙動のようでした。

### 失敗例

素の状態からpipインストールをしようとすると

```
pip install pythonnet
...
/bin/sh: mono: command not found
...
```

monoに起因するようなエラーでインストールが失敗します。([類似エラー](https://stackoverflow.com/questions/62230450/option-not-recognized-error-while-installing-pythonnet))

condaでインストールするとインストールは環境するのですが、

```
conda install -c pythonnet pythonnet
...
Executing transaction: done
```
以下のようにimport clrでmono libraryが見当たらないとなります。リンクエラーですかね。([類似エラー](https://github.com/pythonnet/pythonnet/issues/1034))

``` python
import clr
...
System.DllNotFoundException: /home/ec2-user/anaconda3/envs/python3/lib/../lib/libmono-native.so assembly:<unknown assembly>
...
```

結局SageMaker上というか、monoインストールをcondaに任せる場合、上記のラベルなどを指定しないとうまくいかないという事だと思います。


## Mono-Ubuntu

以下でMonoをインストールします。これでほぼ実行環境は準備完了。

```
sudo apt-get install mono-complete
```

同じ要領でpythonnet を読み込んでチェックします。

``` Python
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form
```

Ubuntu 16.04.6 LTS上の環境を使っています。

``` Python
import sys
print("OS : ", Environment.OSVersion.VersionString)
print("python : " ,sys.version)
print(".NET : ", Environment.Version.ToString())
print("pythonnet : " , clr.__version__)
```

``` :実行結果
OS :  Unix 4.15.0.1063
python :  3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31) 
[GCC 7.3.0]
.NET :  4.0.30319.42000
pythonnet :  2.4.0
```

### .NET Standard ライブラリの呼び出し (成功)

Python for .NET(Mono) ->.NET Standard.NET Standardライブラリの呼び出しを検証しました。

``` Python
sys.path.append("/mnt/azmnt/code/Users/bayesserver-8.16/DotNet/Standard20")
clr.AddReference("BayesServer")
import BayesServer
network = Network()
network.Load("model.bayes")
print(network.Links.Count)
```

どうにか動いているようです。

## .NET Core

# Mac OSX

## Mono

## .NET Core