Python - subprocess.check_call给出了CalledProcessError异常

时间:2012-05-01 12:44:06

标签: python exception subprocess

我想调用子进程来备份mysql数据库。 在终端中运行良好的命令行(并创建了一个名为mydatabase.sql的文件)是:

    mysqldump -uroot -ppassword --add-drop-database --database mydatabase > mydatabase.sql

现在由python运行以调用子进程的代码:

    args = shlex.split('mysqldump -uroot -ppassword --add-drop-database --database mydatabase > mydatabase.sql')
    subprocess.check_call(args)

引发了异常(没有创建文件):

    Traceback (most recent call last):
      File "<pyshell#29>", line 1, in <module>
        subprocess.check_call(args)
      File "/usr/lib/python3.2/subprocess.py", line 485, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['mysqldump', >'-uroot', '-ppassword', '--add-drop-database', '--database', >'mydatabase', '>', 'mydatabase.sql']' returned non-zero exit status 2

我尝试了不同的方法,但它们仍然不起作用:

    args = shlex.split('/opt/lampp/bin/mysqldump -uroot -ppassword --add-drop-database --database mydatabase > mydatabase.sql')
    subprocess.check_call(args)

    args = shlex.split('/opt/lampp/bin/mysqldump -uroot -ppassword --add-drop-database --database mydatabase > mydatabase.sql')
    subprocess.Popen(args)

我也试过shell = True或者shell = False。在这两种情况下,它们仍然不起作用。

我已经阅读了文档,谷歌搜索我的问题的答案,但我还没有弄清楚如何显示我的问题。 stackoverflow可能是我最后的希望。

2 个答案:

答案 0 :(得分:2)

这里的问题是你重定向输出的方式。

  • 如果您将命令作为参数列表传递,那么">"将始终被解释为文字>,无论您使用shell=True还是shell=False < / LI>
  • 如果您将命令作为单个字符串传递,那么它就可以工作,但前提是shell=True
  • 做你想做的最好的方法就是直接从python将输出重定向到文件:

    args = shlex.split('/opt/lampp/bin/mysqldump -uroot -ppassword --add-drop-database --database mydatabase')
    output = open("mydatabase.sql", "w")
    subprocess.Popen(args, stdout=output)
    

答案 1 :(得分:1)

问题可能是shell重定向。如果您使用shell=True投放,请不要使用shlex.split。换句话说,尝试:

args = '/opt/lampp/bin/mysqldump -uroot -ppassword --add-drop-database --database mydatabase > mydatabase.sql'
subprocess.Popen(args,shell=True)

当然,更安全的解决方案是删除shell重定向,在参数上使用shlex.split(不使用shell=True),并使用subprocess.PIPE捕获输出(然后可以发送)到一个文件或在你的程序中做任何你想做的事情)

例如:

args = '/opt/lampp/bin/mysqldump -uroot -ppassword --add-drop-database --database mydatabase'
p=psubprocess.Popen(shlex.split(args),shell=False,stdout=subprocess.PIPE)
p.wait()
returnvalue=p.returncode
data=p.stdout.read()
with open('mydatabase.sql','w') as f:
   f.write(data)

...

如果您不想对程序中的数据执行任何操作,则可以更轻松地进行重定向as described by mata