使用子进程导入SQL转储文件

5
我正在尝试通过Python和subprocess将磁盘上的.sql转储文件导入到MySQL中。即相当于:
mysql -u user -ppassword db < dump.sql

我的Python代码看起来像这样(但我尝试了许多其他方法 :)):

proc = subprocess.Popen(
    ("mysql -u %s -p%s database"  % (MYSQL_USER, MYSQL_PASSWORD)).split(),
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    shell=False)
out, err = proc.communicate('source /tmp/dump.sql')

应用程序成功结束,但没有将任何行导入到MySQL中。我也尝试通过管道方式像这样传输dump.sql
proc = subprocess.Popen(
    ("mysql -u %s -p%s database < /tmp/dump.sql"  % (MYSQL_USER, MYSQL_PASSWORD)).split(),
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    shell=False)
out, err = proc.communicate()

如果我设置shell=True,当出现ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)时,这是一个重要的提示。

请问有人能指导我正确的方向吗?


你正在提供 -ppassword,应该是 -p password。修复后,尝试设置 shell=True。 - Avichal Badaya
我尝试了,但它只显示“ERROR 1045 (28000):拒绝用户'root'@'localhost'的访问(未使用密码)”。这有点正确,因为命令行上的正确语法是-ppassword,而-p password会指示名为password的数据库,对吧? - Sebastian Dahlgren
我的第一个评论适用于当我在命令中使用.split()时。如果我不这样做,那么我会得到mysql帮助文本(例如mysql --help)。 - Sebastian Dahlgren
对于来自Google的任何人,我遇到了同样的问题,但我使用的是-p"{}"(即您用于os.system的内容),而不是-p{}(这是您应该用于subprocess.Popen的内容!!)。 - c z
2个回答

18

如果你从Google来到这个页面,请注意,sigi的答案可以起作用,但它会将所有转储文件加载到内存中,如果文件太大而无法适应,则会失败。

这是我的做法:

with open(dump_filename, 'r') as f: 
       command = ['mysql', '-u%s' % db_settings['USER'], '-p%s' % db_settings['PASSWORD'], db_settings['NAME']]
       proc = subprocess.Popen(command, stdin = f)
       stdout, stderr = proc.communicate()

它的功能相同,但内存消耗最小,因为转储被直接流式传输到mysql的stdin中。


8
您在错误地使用Popen.communicate()方法。
import subprocess

proc = subprocess.Popen(["mysql", "--user=%s" % USER, "--password=%s" % PASS, "database"],
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE)
out, err = proc.communicate(file("/tmp/dump.sql").read())

感谢您的输入,然而结果是一样的。这是新的代码`proc = subprocess.Popen( ("mysql -u %s -p%s database" % (MYSQL_USER, MYSQL_PASSWORD)).split(), stdin=subprocess.PIPE) out, err = proc.communicate(file('/tmp/sebbe').read()) print "out: %s" % out print "err: %s" % err`输出为out: None err: None如果我像您的示例那样跳过split(),我会得到这个错误:OSError: [Errno 2] No such file or directory - Sebastian Dahlgren
如果固定了mysql参数并进行了小规模的测试运行-现在它可以工作了。我的mysql版本是5.5.27。 - sigi
@SebastianDahlgren 你好,这个答案中提供的代码可行吗?我遇到了一个错误,像这样“OSError: [Errno 2] No such file or directory”。我没有使用“split”,最终如何解决这个错误? - nan
@nan,我认为是这样(但那是两年前的事情了,所以我记不清楚细节了)。我猜测你的.sql文件路径可能有误或者你的mysql二进制文件不在PATH中。 - Sebastian Dahlgren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接