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 在某些时候隐含地 join
s 它们——但它可能会先做一些清理。这可能涉及关闭 sys.stdout
.*
事实上,如果您查看 the 2.7 source for threading
,它会在启动时显式隐藏 stderr
,以确保如果主线程已经关闭,它仍然可以打印异常回溯 sys.stderr
.
所以,您尝试做的事情不应该可靠地工作。如果您想绝对确保后台线程(包括那些 运行 Timer
s)可以完全访问所有正常运行时的东西,您需要保持主线程 运行——通常通过 join
他们。 (是的,您可以在 Timer
上调用 join
;正如 the docs 所说,“Timer
是 Thread
的子类。”)
* 发生这种情况的地点和方式的细节已经更改了多次,我不记得 2.7 是如何做到的。最初它只是一个特殊 _MainThread
对象上的 __del__
方法,一旦任何其他线程启动,它就会被创建来代表主线程,但后来有一个 atexit 处理程序,然后特别支持调用threading._shutdown
如果存在,则再次更改以适应模块卸载修复…
您在与 test.py
相同的目录中有一个名为 time.py
的文件。 (或者您确实有一个,并且仍然有 time.pyc
。或者由于某种原因,您的 sys.path
中还有其他地方。)
当您执行 import time
或 from 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 主干,所以这就是我链接到的......无论如何,差异并不重要。
我是运行下面的代码。我从终端输入 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 在某些时候隐含地 join
s 它们——但它可能会先做一些清理。这可能涉及关闭 sys.stdout
.*
事实上,如果您查看 the 2.7 source for threading
,它会在启动时显式隐藏 stderr
,以确保如果主线程已经关闭,它仍然可以打印异常回溯 sys.stderr
.
所以,您尝试做的事情不应该可靠地工作。如果您想绝对确保后台线程(包括那些 运行 Timer
s)可以完全访问所有正常运行时的东西,您需要保持主线程 运行——通常通过 join
他们。 (是的,您可以在 Timer
上调用 join
;正如 the docs 所说,“Timer
是 Thread
的子类。”)
* 发生这种情况的地点和方式的细节已经更改了多次,我不记得 2.7 是如何做到的。最初它只是一个特殊 _MainThread
对象上的 __del__
方法,一旦任何其他线程启动,它就会被创建来代表主线程,但后来有一个 atexit 处理程序,然后特别支持调用threading._shutdown
如果存在,则再次更改以适应模块卸载修复…
您在与 test.py
相同的目录中有一个名为 time.py
的文件。 (或者您确实有一个,并且仍然有 time.pyc
。或者由于某种原因,您的 sys.path
中还有其他地方。)
当您执行 import time
或 from 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 主干,所以这就是我链接到的......无论如何,差异并不重要。