我想创建一个运行多个轻量级线程的程序,但是将其自身限制为一个恒定的,预定义数量的并发运行任务,就像这样(但没有竞争条件的风险):
import threading
def f(arg):
global running
running += 1
print("Spawned a thread. running=%s, arg=%s" % (running, arg))
for i in range(100000):
pass
running -= 1
print("Done")
running = 0
while True:
if running < 8:
arg = get_task()
threading.Thread(target=f, args=[arg]).start()
Run Code Online (Sandbox Code Playgroud)
实现这一目标的最安全/最快的方法是什么?
我正在使用新concurrent.futures模块(也有一个Python 2 backport)来做一些简单的多线程I/O. 我无法理解如何干净地杀死使用此模块启动的任务.
查看以下Python 2/3脚本,它重现了我所看到的行为:
#!/usr/bin/env python
from __future__ import print_function
import concurrent.futures
import time
def control_c_this():
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
future1 = executor.submit(wait_a_bit, name="Jack")
future2 = executor.submit(wait_a_bit, name="Jill")
for future in concurrent.futures.as_completed([future1, future2]):
future.result()
print("All done!")
def wait_a_bit(name):
print("{n} is waiting...".format(n=name))
time.sleep(100)
if __name__ == "__main__":
control_c_this()
Run Code Online (Sandbox Code Playgroud)
当这个脚本运行时,似乎无法使用常规的Control-C键盘中断干净地杀死它.我在OS X上运行.
kill从命令行求助于杀死脚本.Control-C被忽略了.我在网上找到的大多数文档都讨论了如何用旧threading模块干净地杀死线程.这似乎都不适用于此.
concurrent.futures模块中提供的所有停止内容(如Executor.shutdown()和Future.cancel())的方法仅在Futures尚未启动或完成时才起作用,这在这种情况下毫无意义.我想立即打断未来.
我的用例很简单:当用户点击Control-C时,脚本应该像任何行为良好的脚本一样立即退出.这就是我想要的.
那么在使用时获得此行为的正确方法是concurrent.futures什么?
来自https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Executor.map
如果 func 调用引发异常,则在从迭代器检索其值时将引发该异常。
以下代码段仅输出第一个例外 (Exeption: 1),然后停止。这是否与上述说法相矛盾?我希望以下内容打印出循环中的所有异常。
def test_func(val):
raise Exception(val)
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
for r in executor.map(test_func,[1,2,3,4,5]):
try:
print r
except Exception as exc:
print 'generated an exception: %s' % (exc)
Run Code Online (Sandbox Code Playgroud) 我一直在使用concurrent.futures,因为它有一个简单的界面,让用户可以轻松控制线程/进程的最大数量.但是,似乎concurrent.futures隐藏了失败的任务,并在所有任务完成/失败后继续主线程.
import concurrent.futures
def f(i):
return (i + 's')
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
fs = [executor.submit(f, i ) for i in range(10)]
concurrent.futures.wait(fs)
Run Code Online (Sandbox Code Playgroud)
在任何整数上调用f都会导致TypeError.但是,整个脚本运行得很好,并以代码0退出.有没有办法让它在任何线程失败时抛出异常/错误?
或者,有没有更好的方法来限制线程/进程数量而不使用concurrent.futures?
python multithreading multiprocessing python-multithreading concurrent.futures