【问题标题】:Python: Process in one Thread stopping a Process in another Thread from finishingPython:一个线程中的进程阻止另一个线程中的进程完成
【发布时间】:2016-12-29 03:19:02
【问题描述】:

我很感激线程方面的一些帮助,我很新。

示例代码并不完全是我正在做的(“记事本”和“计算”只是示例命令),而是显示我的问题的简化版本。

我想运行两个单独的线程,每个线程多次运行不同的命令。我想要代码来做到这一点:

  1. 同时启动“notepad”和“calc”的第一个实例 (确实如此)
  2. 当我关闭“记事本”实例时,打开 “记事本”的下一个实例。
  3. 当我关闭“calc”实例时, 打开“calc”的下一个实例。
  4. [编辑] 我希望脚本等到两个线程都完成后,因为它需要对这些线程的输出进行一些处理。

但是,当我关闭一个“记事本”实例时,直到我关闭了“计算”的当前实例后,下一个“记事本”实例才会启动,反之亦然。进行一些调试,看起来“记事本”已关闭实例的进程(来自 Popen)在当前“计算”关闭之前不会完成。

在 Windows 7 上运行 Python 2.7

示例代码:

from subprocess import Popen, PIPE, STDOUT
from threading import Thread

def do_commands(command_list):

    for command in command_list:
        proc = Popen("cmd.exe", stdin=PIPE, stdout=PIPE, stderr=STDOUT)
        stdout_value, stderr_value = proc.communicate(input=command)

# MAIN CODE
A_command_list = ["notepad\n", "notepad\n", "notepad\n" ]
B_command_list = ["calc\n", "calc\n", "calc\n" ]

A_args = [A_command_list]
B_args = [B_command_list]

A_thread = Thread(target=do_commands, args=(A_args))
B_thread = Thread(target=do_commands, args=(B_args))

A_thread.start()
B_thread.start()

A_thread.join()
B_thread.join()

提前致谢:-)

尼克

【问题讨论】:

  • 而不是使用Popencommunicate 来启动一个cmd,你不能只启动实际的可执行文件吗?喜欢subprocess.call(['notepad.exe'])? (我没有 Windows,所以你必须找到你必须使用的确切名称)。
  • @Bakuriu - 感谢您的意见。我考虑使用调用,但我需要 stdout 和 stderr 并且文档说“注意不要将此函数与 stdout=PIPE 或 stderr=PIPE 一起使用,因为这可能会根据子进程输出量而死锁。将 Popen 与通信()需要管道时的方法。”
  • @NickFromage 如果您需要标准输出,您可能需要使用check_output。基本上是call+stdout=PIPE 使用communicate 来获取输出。
  • @Bakuriu - 谢谢。我已经用 check_output 而不是 Popen/communicate 试过了。它运行相同,但也有相同的问题(需要'sleep'命令停止它等待两个进程结束)。 check_output 看起来确实有点整洁,所以我将来会尝试使用它。 :-)
  • 我真的不明白为什么需要sleep hack。如果我有时间,我会试着考虑一下。无论如何,我相信sleep 所做的只是触发调度程序。

标签: python multithreading subprocess popen terminate


【解决方案1】:

所以communicate() 方法显然是在等待由Popen 创建并执行cmd.exe 几乎同时开始 的所有进程终止。由于运行calculatorcmd.exe 与运行Notepadcmd.exe 几乎在同一时间启动,因此communicate() 调用(A_thread 中的一个和B_thread 中的一个)都等到两个进程任期.因此,for 循环在两个进程到期之前都不会前进。

在启动两个线程之间添加延迟可以解决问题。

所以,保持原始代码不变并添加

sleep(1)

在两个 Thread starts 之间产生所需的行为。

在我的系统上,添加 0.0001 秒的延迟可以可靠地解决问题,而 0.00001 的延迟则不能。

【讨论】:

  • “sleep(1)”似乎有效。非常感谢您的帮助 :-)
猜你喜欢
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 2015-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 1970-01-01
相关资源
最近更新 更多