Denoからあらゆるpythonライブラリを呼び出すことができる、その名も「python」というライブラリが公開されました。
これは面白そう…!ということで、使ってみようと思います。
使い方
1. Pythonのインストール
最初にPythonをインストールする必要があります。
自分の場合は最初からPythonが入っていたので、この手順は必要ありませんでした。
Pythonが入っていない人は適宜ググってください。
2. Pythonを呼び出すJSコードの作成
まずはfizzbazzを実行してみます。コードは以下のような感じになりました。
import { python } from "https://deno.land/x/python@0.1.0/mod.ts";
// `python.runModule`メソッドは、引数のpythonコードをモジュールとして実行する
const fizzbuzzModule = python.runModule(`
def fizzbuzz(len):
return [
"fizz" if i%6==0
else "buzz" if i%3==0
else "fizzfizz" if i%2==0
else "bazzbazz"
for i in range(len)
]
`);
// `fizzbuzz(10)`の結果はPythonオブジェクトのラッパー
// JSで使える値に変換するには`.valueOf()`メソッドを呼ぶ
for (const i of fizzbuzzModule.fizzbuzz(10).valueOf()) {
console.log(i);
}
ポイントは、
- pythonのコードを
python.runModule
に与えて実行する-
python.runModule
の返り値はimportしたpythonモジュールのように扱える
-
- pythonモジュールからimportした値や、pythonの関数の返り値をJSで扱うには
valueOf()
メソッドを呼ぶ-
valueOf()
自体はJSが暗黙の型変換で呼び出すことが多いので、手動で呼ぶことは少ないかも
-
3. 実行する
実行するのですが、要求されるパーミッションが大きく、--allow-env
/--allow-run
/--allow-read
/--allow-ffi
/--unstable
フラグが必要です。
使用するPythonのdllファイルを指定するために、環境変数DENO_PYTHON_PATH
を指定します。この変数は指定しなくてもいいのですが、指定しない場合は色々なフォルダを読みに行ってdllファイルを探すようで、その場合--allow-read
フラグで大量のフォルダを指定する必要があります。
セキュリティ的にもよくないので、DENO_PYTHON_PATH
を指定してしまったほうがよさそうです。
以下は自分の環境の場合を示します。DENO_PYTHON_PATH
は各自環境に合わせた値を設定してください
# pythonのdllファイルへのパスを環境変数に設定
> set DENO_PYTHON_PATH=C:/Users/azusa/AppData/Local/Programs/Python/Python38/python38.dll
# 実行
> deno run --unstable --allow-env=DENO_PYTHON_PATH --allow-read=DENO_PYTHON_PATH --allow-ffi ./test.ts
fizz
bazzbazz
fizzfizz
buzz
fizzfizz
bazzbazz
fizz
bazzbazz
fizzfizz
buzz
無事、fizzbazzできました。
pythonコードに日本語が含まれているとエラーが出ました。
日本語が含まれているとコードの一部が欠けた状態で実行される?ことがあるようで、奇妙なエラーが発生します。
今後のアップデートで修正されることを期待しましょう。
自分の場合はエディタのプラグイン経由で実行した時に標準出力が受け取れない事がありました。自分の環境に問題があるのかもしれませんが、python内でprint関数を使うときには正しく出力されるか確認したほうがいいかもしれません。
Pythonモジュールを使う
pythonモジュールを直接importすることもできます。
import { python } from "https://deno.land/x/python@0.1.0/mod.ts";
const { print, str } = python.builtins;
const { version } = python.import("sys");
print(str("Hello, World!").lower());
print(`Python version: ${version}`);
> deno run --unstable --allow-env=DENO_PYTHON_PATH --allow-read=DENO_PYTHON_PATH --allow-ffi ./private_check.ts
hello, world!
Python version: 3.8.6 (tags/v3.8.6:db45529, Sep 23 2020, 15:52:53) [MSC v.1927 64 bit (AMD64)]
公式expamleによると、numpyやmatplotlibなども動作するようです。
import { python } from "https://deno.land/x/python@0.1.0/mod.ts";
const np = python.import("numpy");
const plt = python.import("matplotlib.pyplot");
const xpoints = np.array([1, 8]);
const ypoints = np.array([3, 10]);
plt.plot(xpoints, ypoints);
plt.show();
しかし、これを実行したところエラーが発生しました。
error: Uncaught (in promise) PythonError: No module named 'numpy'
throw new PythonError(errorMessage);
^
at maybeThrowError (https://deno.land/x/python@0.1.0/src/python.ts:641:9)
at Python.importObject (https://deno.land/x/python@0.1.0/src/python.ts:717:7)
at Python.import (https://deno.land/x/python@0.1.0/src/python.ts:727:17)
詳しく検証したいところですが、眠いので寝たいと思います
おやすみなさい~