Python subprocess, mysqldump and pipes

烂漫一生 提交于 2019-12-04 13:59:52

I'm not sure of how the pipe will get interpreted. If that's a problem, you can programatically create a pipelilne.

from: http://docs.python.org/library/subprocess.html#replacing-shell-pipeline

p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

edit

As for file redirection, you can direct stdout to a file..

stdin, stdout and stderr specify the executed programs’ standard input, standard output and standard error file handles, respectively. Valid values are PIPE, an existing file descriptor (a positive integer), an existing file object, and None.

Example:

out_file = open(out_filename, "wb")
gzip_proc = subprocess.Popen("gzip", stdout=out_file)
gzip_proc.communicate()

or if you take Alex's advice and use Python's standard library gzip module, you can do something like this:

import gzip
import subprocess

...
#out_filename = path to gzip file

cmdL1 = ["mysqldump", "--user=" + db_user, "--password=" + db_pass, domaindb]
p1 = subprocess.Popen(cmdL1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
dump_output = p1.communicate()[0]

f = gzip.open(out_filename, "wb")
f.write(dump_output)
f.close()

With path, user, pswd and dbname given, the following works like a charm:

import gzip
from subprocess import Popen, PIPE

cmd = "mysqldump --user={user} --password={pswd} {dbname}".format(**locals())        
p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
with gzip.open(path, "wb") as f:
    f.writelines(p.stdout)

using f as stdout argument in subprocess.Popen() also works but does not compress the data. Before Python 2.7, the with statement does not work, so use f=gzip.open(..) and f.close(). Errors can be read with p.stderr.read(), so if this is not an empty string, you better raise an exception


To restore the backup you can do the following:
cmd = "mysql --user={user} --password={pswd} {dbname}".format(**locals())
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
with gzip.open(path, "rb") as f:
    p.stdin.write(f.read())
    p.communicate()[0]
    p.stdin.close()
    p_err = p.stderr.read()
if p_err:
    raise Exception('Error restoring database:\n{0}'.format(p_err))

Try subprocess.Popen(' '.join(cmdL), shell=True).

Pipelines (and redirections) are recognized as such and scheduled by the shell, and, by default (on Unix), subprocess avoids using a shell (it's slower and gives you less control) -- you need to explicitly force a shell to be in control, if a pipeline or redirection is what you absolutely must have.

Normally one tries to avoid pipelines (and therefore avoid shell=True and the attendand issues) by doing as much of that as possible in Python (e.g., in your case, with the gzip module of Python's standard library). Of course for this one must carefully separate stdout (which is to be further processed) from stderr, as two separate pipes.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!