如何防止python中停止主进程的子进程失败

2024-09-27 00:15:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了一个python脚本,在一堆文件上运行一个名为“gtdownload”的多处理命令。“下载”功能是我遇到麻烦的地方。在

#/usr/bin/env python

import os, sys, subprocess
from multiprocessing import Pool

def cghub_dnld_file(file1, file2, file3, np):
    <open files>
    <read in lines>
    p = Pool(int(np))
    map_args = [(line.rstrip(),name_lines[i].rstrip(),bar_lines[i].rstrip()) for i, line in enumerate(id_lines)]
    p.map(download_wrapper,map_args)

def download(id, name, bar):
    <check if file has been downloaded, if not download>
    <.....>
    link = "https://cghub.ucsc.edu/cghub/data/analysis/download/" + id
    dnld_cmd = "gtdownload -c ~/.cghub.key --max-children 4 -vv -d " + link + " > gt.out 2>gt.err"
    subprocess.call(dnld_cmd,shell=True)

def download_wrapper(args):
    return download(*args)

def main():
    <read in arguments>
    <...>
    cghub_dnld_file(file1,file2,file3,threads)

if __name__ == "__main__":
   main()

如果数据库中不存在此文件,gtdownload将退出,这也会终止我的python作业,并出现以下错误:

^{pr2}$

来自gtdownload的实际错误消息:

Welcome to gtdownload-3.8.5a.
Ready to download
Communicating with GT Executive ...
Headers received from the client:  'HTTP/1.1 100 Continue

HTTP/1.1 404 Not Found
Date: Tue, 29 Jul 2014 18:49:57 GMT
Server: Apache/2.2.15 (Red Hat and CGHub)
Strict-Transport-Security: max-age=31536000
X-Powered-By: PHP/5.3.3
Content-Length: 669
Connection: close
Content-Type: text/xml

'

Error:  You have requested to download a uuid which either does not exist within the system, or has not yet reached the 'live' state.  The requested action will not be performed.  Please double check the supplied uuid or contact thelpdesk for further assistance.

我希望脚本跳过一个不存在的,并在下一个脚本上开始gtdownload。我试图输出subprocess.call然后查看是否有“error”关键字。但它似乎停止在确切的subprocess.call命令。同样的事情操作系统. 在

我做了一个没有多重处理的MCV案例,子进程根本没有杀死主进程。看起来多处理会把事情搞得一团糟,尽管我只是用一个线程来测试。在

#!/usr/bin/env python
import subprocess
#THis is the id that gtdownload had problem with
id = "df1e073f-4485-4d5f-8659-cd8eaac17329"
link = "https://cghub.ucsc.edu/cghub/data/analysis/download/" + id
dlnd_cmd = "gtdownload -c ~/.cghub.key --max-children 4 -vv -d " + link + " > gt.out 2>gt.err"
print dlnd_cmd
subprocess.call(dlnd_cmd,shell=True)
print "done"

显然多处理冲突subprocess.call但我不清楚为什么。在


Tags: thegtcmdiddownloaddeflinknot
3条回答

必须使用shell=True才能将subprocess.call与字符串一起用作参数(以及shell重定向):

subprocess.call(dlnd_cmd, shell=True)

如果没有shell=Truesubprocess会尝试将整个命令字符串当作一个单独的可执行名称来处理,这当然不存在,并导致No such file or directory异常。在

请参阅this answer,了解何时使用字符串与何时使用带有subprocess的序列的更多信息。在

subprocess.call不应终止主进程。你的剧本肯定有什么问题,或者你对剧本行为的结论是错误的。您是否尝试在子进程调用后打印一些跟踪输出?在

What is the best way to avoid the failure of subprocess killing the main process?

当然,以适当的方式处理异常并继续前进。在

try:
    subprocess.call(dlnd_cmd)
except OSError as e:
    print 'failed to download: {!r}'.format(e)

但是,这在这里可能不合适。subprocess.call引发的异常通常不是暂时的,您可以记录并解决它;如果它现在不起作用,它将永远无法工作,直到您修复了底层问题(脚本中的一个错误,或者gtdownload没有正确安装,等等)。在

例如,如果您向我们展示的代码是您的实际代码:

^{pr2}$

…那么这保证会引发一个OSError,原因在dano的回答中解释了:call(不带shell=True)将尝试将整个字符串空间、shell重定向等作为在$PATH上查找的可执行程序的名称。没有这样的计划。因此它将引发一个OSError(errno.ENOENT)。(这正是您所看到的)仅仅记录日志对您没有任何好处;您的整个进程都在退出是一件好事,所以您可以调试该问题。在

相关问题 更多 >

    热门问题