我正在使用 Python 作为脚本语言进行一些数据处理和调用命令行工具进行数字计算。因为这些命令行工具是独立的,所以我希望并行运行它们。当一个命令行工具完成时,我可以从输出文件中收集其结果。因此,我还需要一些同步机制来通知我的主 Python 程序一个任务已经完成,以便结果可以被解析到我的主程序中。
目前,我使用 os.system()
,这对单线程很好用,但不能并行化。
谢谢!
我正在使用 Python 作为脚本语言进行一些数据处理和调用命令行工具进行数字计算。因为这些命令行工具是独立的,所以我希望并行运行它们。当一个命令行工具完成时,我可以从输出文件中收集其结果。因此,我还需要一些同步机制来通知我的主 Python 程序一个任务已经完成,以便结果可以被解析到我的主程序中。
目前,我使用 os.system()
,这对单线程很好用,但不能并行化。
谢谢!
如果您想将命令行工具作为单独的进程运行,只需使用os.system
(或更好的:subprocess
模块)异步地启动它们。在Unix/linux/macos上:
subprocess.call("command -flags arguments &", shell=True)
在Windows操作系统中:
subprocess.call("start command -flags arguments", shell=True)
关于如何判断一条命令何时完成:在Unix下,你可以使用wait
等功能,但如果你正在编写命令行脚本,我建议让它们将信息写入文件,并从调用Python脚本监控该文件。
@James Youngman为您的第二个问题提出了一个解决方案:同步。如果您想从Python中控制进程,可以使用Popen以异步方式启动它们。
p1 = subprocess.Popen("command1 -flags arguments")
p2 = subprocess.Popen("command2 -flags arguments")
注意,如果您使用Popen并且您的进程向stdout写入大量数据,则程序将会死锁。请务必将所有输出重定向到日志文件中。
p1
和p2
是您可以用来跟踪您的进程的对象。p1.poll()
不会阻塞,但如果进程仍在运行,则会返回None。它将在进程完成时返回退出状态,因此您可以检查它是否为零。
while True:
time.sleep(60)
for proc in [p1, p2]:
status = proc.poll()
if status == None:
continue
elif status == 0:
# harvest the answers
else:
print "command1 failed with status", status
上述代码只是一个模型:按照现有写法,它永远不会退出,并且会一直“收集”已完成进程的结果。但我相信你已经理解了其意义。if any(p.wait() for p in [p1, p2]):…
。 - Eric O. Lebigot#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Adds my copyright notice to photos.
#
# Author: R.F. Smith <rsmith@xs4all.nl>
# $Date: 2012-10-28 17:00:24 +0100 $
#
# To the extent possible under law, Roland Smith has waived all copyright and
# related or neighboring rights to markphotos.py. This work is published from
# the Netherlands. See http://creativecommons.org/publicdomain/zero/1.0/
import sys
import subprocess
from multiprocessing import Pool, Lock
from os import utime, devnull
import os.path
from time import mktime
globallock = Lock()
def processfile(name):
"""Adds copyright notice to the file.
Arguments:
name -- file to modify
"""
args = ['exiftool', '-CreateDate', name]
createdate = subprocess.check_output(args)
fields = createdate.split(":") #pylint: disable=E1103
year = int(fields[1])
cr = "R.F. Smith <rsmith@xs4all.nl> http://rsmith.home.xs4all.nl/"
cmt = "Copyright © {} {}".format(year, cr)
args = ['exiftool', '-Copyright="Copyright (C) {} {}"'.format(year, cr),
'-Comment="{}"'.format(cmt), '-overwrite_original', '-q', name]
rv = subprocess.call(args)
modtime = int(mktime((year, int(fields[2]), int(fields[3][:2]),
int(fields[3][3:]), int(fields[4]), int(fields[5]),
0,0,-1)))
utime(name, (modtime, modtime))
globallock.acquire()
if rv == 0:
print "File '{}' processed.".format(name)
else:
print "Error when processing file '{}'".format(name)
globallock.release()
def checkfor(args):
"""Make sure that a program necessary for using this script is
available.
Arguments:
args -- list of commands to pass to subprocess.call.
"""
if isinstance(args, str):
args = args.split()
try:
with open(devnull, 'w') as f:
subprocess.call(args, stderr=subprocess.STDOUT, stdout=f)
except:
print "Required program '{}' not found! exiting.".format(args[0])
sys.exit(1)
def main(argv):
"""Main program.
Arguments:
argv -- command line arguments
"""
if len(argv) == 1:
binary = os.path.basename(argv[0])
print "Usage: {} [file ...]".format(binary)
sys.exit(0)
checkfor(['exiftool', '-ver'])
p = Pool()
p.map(processfile, argv[1:])
p.close()
if __name__ == '__main__':
main(sys.argv)
os.system
来调用我的命令行? - Yin Zhusubprocess
来实现。请参考链接中的示例。 - Roland Smith
threading
еТМmultiprocessing
жЬЙеЊИе•љзЪДжФѓжМБгАВдљ†еѓєеЃГдїђжЬЙдїАдєИеЕЈдљУзЪДйЧЃйҐШпЉЯ - Niklas B.