Python 无法显示少数库的输出

Python not able to show output for few libraries

我是运行下面的代码。我从终端输入 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

Python 没有在任何地方记录如果主线程退出而非守护程序后台线程 运行 会发生什么。实际上,至少 CPython 在某些时候隐含地 joins 它们——但它可能会先做一些清理。这可能涉及关闭 sys.stdout.*

事实上,如果您查看 the 2.7 source for threading,它会在启动时显式隐藏 stderr,以确保如果主线程已经关闭,它仍然可以打印异常回溯 sys.stderr .

所以,您尝试做的事情不应该可靠地工作。如果您想绝对确保后台线程(包括那些 运行 Timers)可以完全访问所有正常运行时的东西,您需要保持主线程 运行——通常通过 join他们。 (是的,您可以在 Timer 上调用 join;正如 the docs 所说,“TimerThread 的子类。”)


* 发生这种情况的地点和方式的细节已经更改了多次,我不记得 2.7 是如何做到的。最初它只是一个特殊 _MainThread 对象上的 __del__ 方法,一旦任何其他线程启动,它就会被创建来代表主线程,但后来有一个 atexit 处理程序,然后特别支持调用threading._shutdown 如果存在,则再次更改以适应模块卸载修复…

您在与 test.py 相同的目录中有一个名为 time.py 的文件。 (或者您确实有一个,并且仍然有 time.pyc。或者由于某种原因,您的 sys.path 中还有其他地方。)

当您执行 import timefrom time import sleep 时,它不会打开标准库的 time,而是打开您的 time.py.

即使您不这样做,在 threading:*

from time import time as _time, sleep as _sleep

因此,如果您的 time.py 没有 sleep 方法,这只会引发异常。但如果它 确实 ,那就是事情变得有趣的时候。一切似乎都会正常工作,直到 Timer thread sleeps for 5 seconds by (ultimately) calling a block-and-spin loop inside Condition.wait。如果您的 time.sleep 函数实际上没有休眠,或者如果它将休眠时间乘以 1000 或其他任何原因,这可能会导致它消耗 100% CPU 忙等待,或者需要更长的时间不到 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 主干,所以这就是我链接到的......无论如何,差异并不重要。