【问题标题】:Python script getting killed in middle while launching threadsPython脚本在启动线程时在中间被杀死
【发布时间】:2018-04-10 02:38:12
【问题描述】:

我有一个字典,其中包含 2000 个键值对键作为应用程序的 URL,值作为执行应用程序测试用例的命令。

我需要使用线程并行执行这些,并使用子进程模块启动测试用例命令

在运行一些线程并在标准输出中获得输出后,后续线程卡住并失败。

我尝试检查在我的代码中切出 500 个队列项。它没有受到打击,并且还收到了带有测试用例输出报告的邮件。

请告诉我如何避免在中间敲打螺纹。

我的代码是

import Queue
import subprocess
from threading import Thread
SERVER_COMMANDS = {}
TOTAL_OUTPUT  = []
def run_function(server_commands, receivers, url, test_case_name, mail_send=True):
    threads = []
    q_items = []
    counter = 0
    for server, command in server_commands.iteritems():
        q_items.append(dict(counter=counter,server=server, command=command, server_commands=server_commands))
        counter += 1

    Q = Queue.Queue()
    for item in q_items:
        Q.put(item)

    for i in xrange(90):
      th = Thread(target=_run_function, args=(Q,))
      th.start()
      threads.append(th)
    for th in threads:
      th.join()

    total_output = ''.join(TOTAL_OUTPUT)

def _run_function(q):
    while not q.empty():
        args = q.get()
        server = args.get('server')
        command = args.get('command')
        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
        process.wait()
        output, error = process.communicate()
        print "The thread number is %s" % args.get('counter')
        SERVER_COMMANDS[server] = output
        TOTAL_OUTPUT.append(output)
        for line in output:
            sys.stdout.write(line)

为了获得更好的视野,请查看Result Screenshot

【问题讨论】:

    标签: python multithreading unit-testing subprocess python-multithreading


    【解决方案1】:

    一个问题是q.empty()q.get() 之间存在竞争条件。如果另一个线程获得这两个调用之间的最后一项,则该线程将阻塞。您应该摆脱对q.empty() 的调用,而改为调用q.get_nowait()。然后当它引发Empty 异常时,退出函数。

    但是,我怀疑您真正的问题是您在调用process.communicate() 之前调用了process.wait()。来自docs

    警告这将在使用stdout=PIPE 和/或stderr=PIPE 时出现死锁,并且子进程会向管道生成足够的输出,从而阻塞等待操作系统管道缓冲区接受更多数据。使用communicate() 来避免这种情况。

    别再打电话给process.wait()了。

    您可能还会发现process pool 比启动您自己的更容易。

    【讨论】:

    • 谢谢。通过为 q.get(timeout=10) 指定超时参数,我克服了线程中的挂起问题
    猜你喜欢
    • 2021-05-02
    • 1970-01-01
    • 2014-11-06
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2017-07-12
    • 2013-03-26
    • 2012-09-01
    相关资源
    最近更新 更多