11

以下をファイルhello.pyに入れます(easy_install paramikoまだ取得していない場合):

hostname,username,password='fill','these','in'
import paramiko
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(hostname=hostname, username=username, password=password)
i,o,e = c.exec_command('ls /')
print(o.read())
c.close()

最初の行を適切に入力します。

今すぐ入力

python hello.py

ls の出力が表示されます。

代わりに入力します

python

そして、インタプリタ型の中から

import hello

そして出来上がり!ハングします!コードを関数でラップしfooimport hello; hello.foo()代わりに実行すると、ハングが解除されます。

モジュールの初期化で Paramiko を使用するとハングするのはなぜですか? そもそもParamikoは、モジュールの初期化中に使用されていることをどのように認識していますか?

4

3 に答える 3

18

Paramiko は、基礎となるトランスポートに個別のスレッドを使用します。インポートの副作用としてスレッドを生成するモジュールを持つべきではありません。私が理解しているように、利用可能なインポート ロックは 1 つしかないため、モジュールの子スレッドが別のインポートを試みると、メイン スレッドがまだロックを保持しているため、無期限にブロックされる可能性があります。(私が気付いていない他の落とし穴があるかもしれません)

一般に、インポート時にモジュールに何らかの副作用があってはなりません。そうしないと、予測できない結果が得られます。__name__ == '__main__'トリックで実行を保留するだけで問題ありません。

[編集] このデッドロックを再現する簡単なテスト ケースを作成できないようです。認証コードは決して発生しないイベントを待っているため、インポートのスレッド化の問題だと思います。これは、paramiko または python のバグである可能性がありますが、良いニュースは、正しく実行すれば、これが表示されることはないということです ;)

これは、常に副作用を最小限に抑えたい理由と、関数型プログラミング手法がより普及している理由の良い例です。

于 2009-01-16T16:01:36.910 に答える