如何在Python中获取进程ID
我正在使用一个基于Linux的集群系统(网址:www.mosix.org),这个系统可以让我在不同的电脑上运行任务。任务的运行方式如下:
mosrun ls &
这样做会在后台创建一个进程,并返回这个进程的ID,像这样:
[1] 29199
之后它会返回结果。我正在写一个Python程序,用来运行和控制这些任务。为了实现这个目标,我想像上面那样使用mosrun程序来运行任务,并保存新创建的进程的ID(在这个例子中是29199)。这显然不能通过os.system或commands.getoutput来完成,因为打印出来的ID并不是进程输出的内容……有没有什么建议?
补充说明:
因为这个Python脚本只是用来最初运行任务,所以这些任务需要运行的时间比Python脚本本身要长。我想这意味着mosrun进程不能是这个脚本的子进程。有什么建议吗?
谢谢
3 个回答
感谢大家的帮助。最后我做了这些,看起来效果还不错。这个代码使用了 python-daemon。也许在把子进程的ID传给父进程时,可以做得更聪明一些,但这部分相对简单。
import daemon
def run_in_background(command, tmp_dir="/tmp"):
# Decide on a temp file beforehand
warnings.filterwarnings("ignore", "tempnam is a potential security")
tmp_filename = os.tempnam(tmp_dir)
# Duplicate the process
pid = os.fork()
# If we're child, daemonize and run
if pid == 0:
with daemon.DaemonContext():
child_id = os.getpid()
file(tmp_filename,'w').write(str(child_id))
sp = command.split(' ')
os.execl(*([sp[0]]+sp))
else:
# If we're a parent, poll for the new file
n_iter = 0
while True:
if os.path.exists(tmp_filename):
child_id = int(file(tmp_filename, 'r').read().strip())
break
if n_iter == 100:
raise Exception("Cannot read process id from temp file %s" % tmp_filename)
n_iter += 1
time.sleep(0.1)
return child_id
可以使用 subprocess
这个模块。通过这个模块创建的 Popen
实例有一个叫 pid
的属性。
看起来你想确保子进程是守护进程。PEP 3143文档中有关于这个的说明,并且提供了一些参考实现。
一旦你的进程(仍在运行Python代码)被设置为守护进程,不管是通过PEP 3143提供的方法还是其他方式,你可以使用os.execl(或者其他的os.exec...
函数)来运行你的目标代码——这会在我们刚刚提到的那个守护进程中运行目标代码,因此它会保持守护进程的状态,正如你所希望的那样。
最后一步不能使用subprocess
,因为它需要在同一个(守护进程)中运行,覆盖其可执行代码——这正是os.execl
和其他相关函数的用途。
在守护进程化之前的第一步,理论上可以通过subprocess
来完成,但这样做有点麻烦(你需要把守护进程化和os.exec的代码放在一个单独的.py
文件中):通常你会想要直接使用os.fork
,然后立即将子进程设置为守护进程。
subprocess
是一个相当方便的跨平台方式来运行其他进程,但在一些高级用法(比如守护进程化)上,它并不能完全替代Unix的“fork和exec”方法——这就是为什么Python标准库也提供了通过os
模块中的那些函数来实现这一点的好处!