假设我们有一个主线程为测试模块启动两个线程 - “test_a”和“test_b”。 两个测试模块线程都保持其状态,无论它们是否已完成执行测试,或者是否遇到任何错误,警告或是否要更新其他信息。
主线程如何访问此信息并采取相应措施。 例如,如果“test_a”引发了错误标志; “main”如何知道并在出现错误之前停止其余的测试?
这样做的一种方法是使用全局变量,但这很难看。很快。
答案 0 :(得分:5)
显而易见的解决方案是通过将它传递给构造函数/ start中的线程对象/函数来共享某种可变变量。
这样做的干净方法是使用适当的实例属性构建一个类。如果你使用的是threading.Thread
subclass,而不仅仅是一个线程函数,你通常可以使用子类本身作为粘贴这些属性的地方。但我会用list
显示它只是因为它更短:
def test_a_func(thread_state):
# ...
thread_state[0] = my_error_state
# ...
def main_thread():
test_states = [None]
test_a = threading.Thread(target=test_a_func, args=(test_states,))
test_a.start()
您可以(通常也希望)将Lock
或Condition
打包到可变状态对象中,这样您就可以在main_thread
和test_a
之间正确同步。 / p>
(另一种选择是使用queue.Queue
,os.pipe
等来传递信息,但是你仍然需要将该队列或管道传递给子线程 - 你在与上面完全相同。)
然而,值得考虑的是你是否真的需要这样做。如果您将test_a
和test_b
视为“作业”,而不是“线程函数”,则可以只在池上执行这些作业,并让池处理传递结果或错误。
例如:
try:
with concurrent.futures.ThreadPoolExecutor(workers=2) as executor:
tests = [executor.submit(job) for job in (test_a, test_b)]
for test in concurrent.futures.as_completed(tests):
result = test.result()
except Exception as e:
# do stuff
现在,如果test_a
函数引发异常,主线程将获得该异常 - 因为这意味着退出with
块,并且所有其他作业都被取消并丢弃,并且工作线程关闭。
如果您使用的是2.5-3.1,则内置concurrent.futures
,但可以安装the backport off PyPI,或者可以重写multiprocessing.dummy.Pool
周围的内容。 (这是稍微那么复杂,因为你必须创建一系列作业并调用map_async
来取回AsyncResult
对象上的迭代器......但实际上这仍然很简单。)