Python 线程化/生成多个OS命令并在不同点获得输出的最佳方法
我正在努力寻找并行运行多个操作系统命令并能够从中捕获输出的最佳方法。OS命令是一个半长时间运行的专有实用程序,用C语言编写(在solaris/linux主机上运行,使用python 2.4),该脚本将从作业队列中提取作业,为每个作业实例化一个类,然后该类使用提供的参数生成OS实用程序。这个类实际上还有很多内容,但是只关注脚本的整体架构,在这个上下文中省略的代码是微不足道的 实际上有两个点需要这个OS命令的输出 当第一次执行命令时,它返回一个jobid,我需要捕获它。然后,该命令将阻塞,直到完成。然后我需要捕获这个命令的返回代码 我真正想做的(我想)是定义一个类,它生成一个线程,然后执行Popen() 以下是我现在拥有的:Python 线程化/生成多个OS命令并在不同点获得输出的最佳方法,python,subprocess,python-multithreading,python-2.4,Python,Subprocess,Python Multithreading,Python 2.4,我正在努力寻找并行运行多个操作系统命令并能够从中捕获输出的最佳方法。OS命令是一个半长时间运行的专有实用程序,用C语言编写(在solaris/linux主机上运行,使用python 2.4),该脚本将从作业队列中提取作业,为每个作业实例化一个类,然后该类使用提供的参数生成OS实用程序。这个类实际上还有很多内容,但是只关注脚本的整体架构,在这个上下文中省略的代码是微不足道的 实际上有两个点需要这个OS命令的输出 当第一次执行命令时,它返回一个jobid,我需要捕获它。然后,该命令将阻塞,直到完成。
#!/usr/bin/python
import sys, subprocess, threading
cmd = "/path/to/utility -x arg1 -y arg2"
class Command(object):
def __init__(self, cmd):
self.cmd = cmd
self.process = None
self.returncode = None
self.jobid = None
def __call__(self):
print "Starting job..."
self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
out, err = self.process.communicate()
self.jobid = out.split()[10]
def alive(self):
if self.process.poll():
return True
else:
return False
def getJobID(self):
return self.jobid
job = Command(cmd)
jobt = threading.Thread(target=job, args=[])
jobt.start()
# if job.alive():
# print "Job is still alive."
# do something
# else:
# print "Job is not alive."
# do something else
sys.exit(0)
这里的问题是使用p.communicate()会导致整个线程阻塞,并且我无法在想要的位置获取作业ID
另外,如果我取消对if语句的注释,它会抱怨没有活动的方法()
我尝试过各种不同的方法,比如在类的call方法内部创建线程,但这似乎走错了路
在生成线程时,我还尝试将类名指定为目标参数:
jobt = threading.Thread(target=Command, args=[cmd])
jobt.start()
我使用的每一种方法都会遇到障碍
谢谢你的建议
所以在尝试了dano的想法后,我现在有了这个:
class Command(threading.Thread):
def __init__(self, cmd):
super(Command, self).__init__()
self.cmd = cmd
self.process = None
self.returncode = None
self.jobid = None
def run(self):
print "Starting job..."
self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, shell=False)
print "Getting job id..."
out = self.process.stdout.readline()
print "out=" + out
self.returncode = self.process.wait()
def alive(self):
if self.process.poll():
return True
else:
return False
def getJobID(self):
return self.jobid
job = Command(cmd)
job.start()
这将产生以下输出:
Starting job...
Getting job id...
此时,它将挂起,直到OS命令完成
下面是手动运行此命令的示例。输出的前两行立即返回
$ /path/to/my/command -x arg1 -y arg2
Info: job request 1 (somestring) submitted; job id is 729.
Info: waiting for job completion
# here is hangs until the job is complete
Info: job 729 completed successfully
再次感谢您的帮助。我认为您可以通过使用
命令
从线程继承来简化事情。线程
:
import sys
import subprocess
import threading
cmd = "/path/to/utility -x arg1 -y arg2"
class Command(threading.Thread):
def __init__(self, cmd):
super(Command, self).__init__()
self.cmd = cmd
self.process = None
self.returncode = None
self.jobid = None
def run(self):
print "Starting job..."
self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
out, err = self.process.communicate()
self.jobid = out.split()[10]
def alive(self):
if self.process.poll():
return True
else:
return False
def getJobID(self):
return self.jobid
job = Command(cmd)
job.start()
if job.alive():
print "Job is still alive."
else:
print "Job is not alive."
sys.exit(0)
在命令实际退出之前,不能使用self.process.communicate()
获取作业id,因为communicate()
将在程序完成之前阻塞。相反,您需要使用直接从进程读取'stdout
:
self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, bufsize=0, shell=True)
out = self.process.stdout.readline()
self.jobid = out.split()[10]
请注意,添加了bufsize=0
,因此请尽量避免子进程缓冲其输出,这可能导致readline
阻塞
然后,您可以调用communicate
或wait
等待进程结束:
self.returncode = self.process.wait()
它抱怨“AttributeError:'Command'对象没有属性'\u lock'”。然后我将其更改为“self.Lock()”并得到相同的错误。在这里使用lock到底有什么意义?Thx。@BenH抱歉,这是复制粘贴错误。现在已修复。我喜欢这种方法,但是“out=self.process.stdout.readline()”似乎也会阻塞:@BenH您不能将其添加为注释。你得把它编辑成你的问题。@BenH是的,有点尴尬。通常提问者会在原始问题的末尾添加一个新的部分,标记为Edit:。