我正在linux上的python 3.4中创建一个带有Web前端的自定义作业调度程序。该程序创建一个守护进程(消费者)线程,等待PriorityQueue中可用的作业。可以通过Web界面手动添加这些作业,将其添加到队列中。当用户线程找到一个作业时,它使用subprocess.run执行一个程序,并等待它完成。
工作线程的基本思想:
class Worker(threading.Thread):
def __init__(self, queue):
self.queue = queue
# more code here
def run(self):
while True:
try:
job = self.queue.get()
#do some work
proc = subprocess.run("myprogram", timeout=my_timeout)
#do some more things
except TimeoutExpired:
#do some administration
self.queue.add(job)
然而:
我应该使用哪些同步原语来中断此线程或确保它以阻塞方式同时等待多个事件?
答案 0 :(得分:1)
我认为你不小心掩盖了一个简单的解决方案:你的第二个要点是你有能力杀死在子进程中运行的程序。请注意subprocess.call
returns the return code of the subprocess。这意味着您可以让主线程终止子进程,只需检查返回代码以查看是否需要进行任何清理。更好的是,您可以使用subprocess.check_call代替,如果返回码不是0,将为您引发异常。我不知道您正在使用什么平台,但在Linux上,已杀死的进程通常不会如果他们被杀,则返回0.
看起来像这样:
class Worker(threading.Thread):
def __init__(self, queue):
self.queue = queue
# more code here
def run(self):
while True:
try:
job = self.queue.get()
#do some work
subprocess.check_call("myprogram", timeout=my_timeout)
#do some more things
except (TimeoutExpired, subprocess.CalledProcessError):
#do some administration
self.queue.add(job)
请注意,如果您使用的是Python 3.5,则可以改为使用subprocess.run,并将check
参数设置为True
。
如果您非常需要处理不运行子进程时工作者需要中断的情况,那么我认为您将不得不使用轮询循环,因为我不认为Python中的线程支持您正在寻找的行为。您可以使用threading.Event对象将“现在停止工作”伪信号从主线程传递给工作者,并让工作人员定期检查该事件对象的状态。
如果您愿意考虑使用多个处理代替线程,请考虑切换到multiprocessing module,这将允许您处理信号。产生完整的子进程而不是线程有更多的开销,但你实际上是在寻找类似信号的异步行为,我不认为Python的线程库支持这样的东西。但是,一个好处是,您可以从Global Interpreter Lock(PDF链接)中解脱出来,因此如果您的工作进程(以前的线程)正在执行任何CPU密集型操作,您实际上可能会看到一些速度优势。