我有一个程序需要运行多个可执行文件,我想通过并行运行这些文件来提高性能。
我的基本代码看起来像这样:
import subprocess
def run_exe(input_command):
p = subprocess.Popen('example.exe',stdin=subprocess.PIPE,stdout=subprocess.PIPE)
p.communicate(bytes(input_command,'utf-8'))
if __name__ == '__main__':
run_exe('task_1')
run_exe('task_2')
我想要多线程或多处理它,但是当我这样做时它不起作用。我检查了 stdout,看起来 p.communicate 发送的 input_command 没有被确认(stdout 有一个“等待输入”消息)。我在网上看到一个模糊的参考资料,其中提到 p.communicate 可能只能在主进程上正常工作,但海报没有提供任何其他详细信息来说明原因或任何潜在的解决方法。这是我要实现的多线程代码的示例:
import subprocess
import threading
def run_exe(input_command):
p = subprocess.Popen('example.exe',stdin=subprocess.PIPE,stdout=subprocess.PIPE)
p.communicate(bytes(input_command,'utf-8'))
if __name__ == '__main__':
t1 = threading.Thread(run_exe,('task_1',))
t2 = threading.Thread(run_exe,('task_2',))
t1.start()
t2.start()
t1.join()
t2.join()
但如上所述,可执行文件未正确接收输入。
我建议使用
concurrent.futures
,它是一个包装器,比直接使用线程更简单。
import concurrent.futures
import logging
import subprocess
def run_exe(input_command: str):
process = subprocess.run(
["example.exe"],
input=input_command,
text=True,
stdout=subprocess.PIPE,
)
return process.stdout
def main():
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s | %(levelname)-8s | %(threadName)-24s | %(message)s",
datefmt="%H:%M:%S",
)
logging.info("Start")
with concurrent.futures.ThreadPoolExecutor() as executor:
output = [(arg, executor.submit(run_exe, arg)) for arg in ["task_1", "task_2"]]
for arg, future in output:
logging.info("%s --> %s", arg, future.result())
logging.info("End")
if __name__ == "__main__":
main()
输出:
11:16:12 | INFO | MainThread | Start
11:16:15 | INFO | MainThread | task_1 --> Output for task_1
11:16:15 | INFO | MainThread | task_2 --> Output for task_2
11:16:15 | INFO | MainThread | End
subprocess.run()
,强烈推荐它而不是Popen
input=input_command
是我向进程发送文本的方式' stdintext=True
,这样我就不必对输入/输出进行编码/解码ThreadPoolExecutor
启动了一个线程池,我也可以使用ProcessPoolExecutor
,因为它们具有相同的接口
output
是(输入,未来)with
语句时,我可以确定所有任务都已完成