2

以下のコードを実行しています。ターミナルから私は入れていpython test.pyます。しかし、それは私に何も与えていません。

###test.py### Version 2
from threading import Timer

def hello():
    print "Hello"

t=Timer(5, hello)
t.start()

別のマシンで同じコードを試してみましたが、出力が正しく表示されています。一歩一歩進んでみました。printステートメントのみを保持しましたが、正常に機能しています。次に、その出力を関数に追加し、関数を呼び出しましたが、正常に動作しています。を追加するとすぐにTimer、強制的に停止するまで、python コマンドは出力を表示せずに実行を続けます。

以前は、scapyライブラリでも同じことが起こりました。しかし、システムの再起動後は正常に機能しました。ただし、システムの再起動後も機能しません。

何が問題なのですか?

注 1: 6 日前には、このような動作はしていませんでした。マルウェアの可能性はありますか?

注 2:特異な動作。

###test.py### Version 1

from threading import Timer
from time import sleep

def hello():
    print "Hello"

t=Timer(5, hello)
t.start()
sleep(10)

これが私のバージョン 1 でした。うまくいかなかったので、上記のバージョン 2 に変更しました。まだ出力はありません。ctrlしかし、 +を押すcと、表示されます

  from time import sleep as _sleep
 File .........., line 2, in <module>
KeyboardInterrupt

そのコード行はそこにはありませんが。保存したかどうかに関係なく、保存したファイルを再確認しました。pycまた、問題を引き起こしているファイルがないかどうかも確認しました。しかし、そこにはありませんpycでした。

4

2 に答える 2

1

time.pyと同じディレクトリにという名前のファイルがありますtest.py。(または、1つ持っていて、まだ持っていtime.pycます。またはsys.path、何らかの理由で別の場所に持っています。)

import timeまたはを実行するとfrom time import sleep、stdlib が開かれるのではなくtimetime.py.

そして、あなたがそれをしなくても、内部threading*

from time import time as _time, sleep as _sleep

したがって、メソッドtime.pyがない場合はsleep、例外が発生します。しかし、もしそうなら、それ物事が楽しくなるときです. Timerスレッドが (最終的に) 内でブロック アンド スピン ループを呼び出して 5 秒間スリープするまで、すべてが正常に機能しているように見えますCondition.wait。関数が実際にスリープしていない場合time.sleep、またはスリープ時間を 1000 倍するなどの理由で、待機中の CPU を 100% 消費するか、起動に 5 秒以上かかるか、または誰にもわからない場合何。

同様に、scapyほぼ確実にtimeモジュールを使用しているため、同じ問題が発生しています。


いずれにせよ、これは非常に簡単にテストできます。

$ python2.7
>>> import time
>>> time.__file__
/usr/lib/python2.7/lib-dynload/time.so
>>> import threading
>>> threading.__file__
/usr/lib/python2.7/threading.pyc

結果がそれに似ていない場合は、問題があります。


※手元にある 2.7.6 のコピーは少し違いますが、Fedora 21 は 2.7.6 よりも最新の 2.7 トランクに近いと思いますので、そこにリンクを張っています。 .

于 2015-04-20T06:33:23.027 に答える
0

Python は、非デーモン バックグラウンド スレッドの実行中にメイン スレッドが終了した場合に何が起こるかをどこにも文書化していません。実際には、少なくとも CPythonjoinはある時点でそれらを暗黙的に s しますが、最初に何らかのクリーンアップを行う場合があります。これには、おそらく終了が含まれる可能性がありsys.stdoutます。*

実際、の 2.7 ソースをthreadingstderr見ると、メイン スレッドが既に閉じている場合でも例外トレースバックを確実に出力できるようにするために、起動時に明示的に隠していsys.stderrます。

したがって、あなたがやろうとしていることは、確実に機能するはずがありません。バックグラウンド スレッド (実行中Timerの s を含む) がすべての通常の実行時処理に完全にアクセスできるようにしたい場合は、メイン スレッドを実行し続ける必要があります (通常はjoining によって)。join(はい、Timer; を呼び出すことができます。ドキュメントにあるように、「Timerは のサブクラスですThread。」)


* これがどこでどのように発生するかの詳細は何度も変更されており、2.7 でどのように変更されたか正確には覚えていません。もともとは、他のスレッドが開始されるとすぐにメインスレッドを表すために作成される__del__特別なオブジェクトのメソッドでしたが、後に atexit ハンドラーがあり、存在する場合は呼び出すための特別なサポートがあり、再び変更されましたモジュールのアンロード修正に適合…</sub>_MainThreadthreading._shutdown

于 2015-04-20T05:55:02.080 に答える