Mat*_*hew 5 python multithreading python-3.x
我正在尝试一个以用户可以随时停止其执行而无需停止主程序的方式执行一段代码的程序。我以为我可以使用 threading.Thread 来做到这一点,但后来我在 IDLE (Python 3.3) 中运行了以下代码:
from threading import *
import math
def f():
eval("math.factorial(1000000000)")
t = Thread(target = f)
t.start()
Run Code Online (Sandbox Code Playgroud)
最后一行没有返回:我最终重新启动了 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()
Run Code Online (Sandbox Code Playgroud)
最后一行返回 False,即使我在启动该过程后仅几秒钟就运行了它!根据我的处理器使用情况,我被迫得出结论:该过程从一开始就从未启动过。有人可以解释一下我在这里做错了什么吗?
Thread.start() 永远不会返回!这可能与数学库的 C 实现有关吗?
正如@eryksun在评论中指出的那样:math.factorial() 是作为 C 函数实现的,不会释放 GIL,因此在它返回之前不会运行其他 Python 代码。
注意:multiprocessing版本应该按原样工作:每个Python进程都有自己的GIL。
factorial(1000000000)有数亿位数字。尝试import time; time.sleep(10)作为虚拟计算。
如果您在 IDLE 中遇到多线程代码问题,请在命令行中尝试相同的代码,以确保错误仍然存在。
如果在已经调用之后p.is_alive()返回,则可能意味着函数中有错误,例如。Falsep.start()f()MemoryError
在我的机器上,如果我将问题中的代码粘贴到 Python shell 中,p.is_alive()则会返回True并且其中一个 cpu 处于 100%。
不相关:删除通配符导入,例如from multiprocessing import *. 它们可能会掩盖代码中的其他名称,以便您无法确定给定名称的含义,例如,threading可以使用类似但不同的语义定义eval函数(它没有,但可以),这可能会默默地破坏您的代码。
我希望我的程序能够优雅地处理用户的荒谬输入
如果您直接将用户输入传递给用户,eval()那么用户就可以执行任何操作。
有没有什么方法可以让进程在不构建管道或其他类似结构的情况下打印错误消息?
这是一段普通的Python代码:
print(message) # works
Run Code Online (Sandbox Code Playgroud)
不同之处在于,如果运行多个进程print(),则输出可能会出现乱码。您可以使用锁来同步调用print()。