我有三个shell脚本P1,P2和P3,我试图链接。这三个shell脚本需要串行运行,但在任何给定时间都可以运行多个P1,P2和P3。
我需要在数十个文件上快速运行这些文件,因此需要使用Threads并且并行执行。
我正在使用python Thread,Queue和subprocess模块来实现这一目标。
我的问题是,当我的线程数大于1时,程序行为不规律,并且线程不会以可重现的方式相互交换。所有五个线程都可以完美运行并完成工作。
这是我第一次尝试使用线程进行操作,我确信这是因为Threads涉及竞争条件的常见问题。但我想知道如何清理我的代码。
实际代码位于(https://github.com/harijay/xtaltools/blob/master/process_multi.py)。伪代码如下。对不起,如果代码很乱。
我的问题是为什么我使用这种设计会有不稳定的行为。线程在任何给定时间都访问不同的文件。此外,subprocess.call仅在shell脚本完成且其生成的文件写入磁盘时返回。
我能做些什么不同的事情? 我试图尽可能简洁地解释我的设计。
我的基本设计:
P1_Queue = Queue()
P2_Queue = Queue()
P3_Queue = Queue()
class P1_Thread(Thread):
def __init__(self,P1_Queue,P2_Queue):
Thread.__init__(self)
self.in_queue = P1_Queue
self.out_queue = P2_Queue
def run(self):
while True:
my_file_to_process = self.in_queue.get()
if my_file_to_process = None:
break
P1_runner = P1_Runner(my_file_to_process)
P1_runner.run_p1_using_subprocess()
self.out_queue.put(my_file_to_process)
类p1 Runner获取输入文件句柄,然后调用subprocess.call()以运行使用文件输入的shell脚本,并使用run_p1_using_subprocess方法生成新的输出文件。
class P1_runner(object):
def __init__(self,inputfile):
self.my_shell_script = """#!/usr/bin/sh
prog_name <<eof
input 1
...
eof"""
self.my_shell_script_file = open("some_unique_p1_file_name.sh")
os.chmod("some_unique_file_name.sh",0755)
def run_p1_using_subprocess(self):
subprocess.call([self.my_shell_script_file])
I have essentially similar classes for P2 and P3 . All of which call a shell script that is custom generated
The chaining is achieved using a series of Thread Pools.
p1_worker_list = []
p2_worker_list = []
p3_worker_list = []
for i in range(THREAD_COUNT):
p1_worker = P1_Thread(P1_Queue,P2_Queue)
p1_worker.start()
p1_worker_list.append(p1_worker)
for worker in p1_worker_list:
worker.join()
And then again the same code block for p2 and p3
for i in range(THREAD_COUNT):
p2_worker = P2_Thread(P2_Queue,P3_Queue)
p2_worker.start()
p2_worker_list.append(p1_worker)
for worker in p2_worker_list:
worker.join()
感谢您的帮助/建议
答案 0 :(得分:2)
这真的很糟糕:
runner.run()
你不应该手动调用线程的run方法。你用.start()开始一个线程。你的代码是一个巨大的混乱,这里没有人会通过它来找到你的错误。
答案 1 :(得分:1)
当另一个线程清空其输入队列时,线程的退出条件会使它们自杀:
my_file_to_process = self.in_queue.get()
if my_file_to_process = None: # my sister ate faster than I did, so...
break # ... I kill myself!
线程正在消亡只是因为当他们准备好更多时他们没有找到工作要做。
你应该让线程进入休眠状态(等待)直到它们的输入队列上的事件发出信号,只有当协调器(主程序)发出信号表明处理完成时才设置死亡(设置自杀标志,并发出所有队列信号) )。
(我看到你已经改变了代码)。
@Falmarri在其他地方的说明中可能意味着你的问题不是关于特定问题(其他人可以回答的问题),因为代码中threading
库的整体使用是错误的,并且你使用的是编程语言一般都很尴尬。例如:
worker.join()
的调用使主程序在启动P2线程之前按顺序等待所有P1线程的终止,从而击败任何并发尝试。Thread.run()
或为构造函数提供可调用项。不需要Pn_runner
类。我建议你解决这个特殊问题的建议是:
如果您打算自学Python中的线程,那么请务必寻找一个简单的问题来进行实验。如果您想要的是并行运行多个shell脚本,那么bash
和其他shell已经有了相应的规定,您不需要使用Python。