我正在尝试以某种方式执行一段代码的程序,以便用户可以随时停止其执行而无需停止主程序。我以为可以使用threading.Thread做到这一点,但是后来我在IDLE(Python 3.3)中运行了以下代码:
from threading import *
import math
def f():
eval("math.factorial(1000000000)")
t = Thread(target = f)
t.start()
最后一行不返回:我最终重新启动了Shell。这是全局解释器锁定的结果,还是我做错了什么?我在线程文档(http://docs.python.org/3/library/threading.html)中没有看到针对此问题的任何特定内容。
我试图用一个过程做同样的事情:
from multiprocessing import *
import math
def f():
eval("math.factorial(1000000000)")
p = Process(target = f)
p.start()
p.is_alive()
最后一行返回False,即使我在开始该过程后仅几秒钟就运行了它!根据我的处理器使用情况,我不得不得出结论,该过程从一开始就没有开始。有人可以在这里解释我做错了什么吗?
Thread.start()永不返回!这与数学库的C实现有关吗?
正如@eryksun在评论中指出的那样:math.factorial()被实现为不释放GIL的C函数,因此直到返回其他Python代码都无法运行。
注意:multiprocessing
版本应按原样工作:每个Python进程都有自己的GIL。
factorial(1000000000)
有数亿个数字。尝试import time; time.sleep(10)
作为虚拟计算。
如果您对IDLE中的多线程代码有疑问,请从命令行尝试相同的代码,以确保错误仍然存在。
如果p.is_alive()
返回False
后p.start()
已经叫,那么它可能意味着有一个错误f()
的功能,例如,MemoryError
。
在我的机器上,如果我将问题中的代码粘贴到Python Shell中,则p.is_alive()
返回True
cpus之一为100%。
不相关:删除通配符导入,例如from multiprocessing import *
。它们可能会在代码中掩盖其他名称,以使您无法确定给定名称的含义,例如,threading
是否eval
可以使用相似但不同的语义定义函数(它不能,但是可以)可能会无声地破坏您的代码。
我希望我的程序能够优雅地处理来自用户的荒谬输入
如果直接将用户输入传递给用户,eval()
则用户可以执行任何操作。
有没有办法在不构造管道或其他类似结构的情况下获得打印过程(例如,错误消息)的方法?
这是一个普通的Python代码:
print(message) # works
区别在于,如果运行多个进程,print()
则输出可能会出现乱码。您可以使用锁来同步print()
呼叫。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句