4

我正在编写一个简单的 Python 脚本来复制 MySQL 数据库。我正在尝试根据以下 SO 问题及其答案复制数据库:“复制/复制数据库而不使用 mysqldump ”、“ python 子进程和 mysqldump ”和“ Python 子进程、mysqldump 和管道”。但是,由于某些原因,我的脚本无法正常工作,因为表格和数据没有出现在我的新数据库中。

我可以从我的输出中看到 mysqldump 工作正常(我在输出中看到“Dump completed on...”),所以我认为我的管道有问题

这是我的脚本:

#!/usr/bin/env python

import pymysql
from subprocess import Popen, PIPE, STDOUT

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='mydb')
cur = conn.cursor()

print("Attempting to create new database...")
try:
    cur.execute("CREATE DATABASE mydb2")
    print("Creating new database")
except Exception:
    print("Database already exists")
print()

# close connection just to be sure
cur.close()
conn.close()

print("Trying to copy old database to new database...")

args1 = ["mysqldump", "-h", "localhost", "-P", "3306", "-u", "root", "-p", "mydb"]
args2 = ["mysql", "-h", "localhost", "-P", "3306", "-u", "root", "-p", "mydb2"]

p1 = Popen(args1, stdout=PIPE, stderr=STDOUT)
p2 = Popen(args1, stdin=p1.stdout, stdout=PIPE, stderr=STDOUT)
output = p2.communicate()

print("output:")
print(output)
print()

如您所见,我从这个答案中获取了复制数据库管道。起初我和其他问题mysqldump: Couldn't find table: "|"一样遇到了错误。所以现在我按照建议使用两个调用,这解决了该错误消息。subprocess.Popen

输出变量显示执行了 mysqldump,但我没有看到关于 mysql 命令的任何内容。

我曾尝试使用p2.wait()andp1.wait()而不是p2.communicate() 一个答案中的建议,但这只会使我的 Python 脚本变得无响应。

我还尝试了以下方法:

output1 = p1.communicate()
output2 = p2.communicate()

但是 output1 和 output2 都显示了相同的 mysqldump 输出。所以我猜这只是一件愚蠢的事情。

我也尝试过使用subprocess.call而不是subprocess.Popen,但这也使我的脚本变得无响应。

还包括其中shell=True一个Popencall还导致脚本只是无响应。

但是,在命令提示符(我使用 Windows 8.1)中键入命令确实有效,如下所示:

mysqldump -h localhost -P 3306 -u root -p mydb | mysql -h localhost -P 3306 -u root -p mydb2

它在不到三秒的时间内复制了我的小型测试数据库。

我希望我也可以让它在 Python 中工作。

4

4 回答 4

15

我不知道您要用于复制的纯 Python程度,但您可以将整个管道操作委托给 shell。

subprocess.Popen('mysqldump -h localhost -P 3306 -u -root mydb | mysql -h localhost -P 3306 -u root mydb2', shell=True)

这应该与在 shell 上运行它时的工作方式相同。

于 2014-10-08T20:53:57.547 回答
5

我看到的一个问题是在这一行:

p2 = Popen(args1, stdin=p1.stdout, stdout=PIPE, stderr=STDOUT)

它应该是:

p2 = Popen(args2, stdin=p1.stdout, stdout=PIPE, stderr=STDOUT)

(args1 被传递给第二个 proc,因此程序进行了两次转储和零恢复)

于 2015-02-18T23:53:25.020 回答
3

当我尝试执行相同的任务时,我不断回到这篇文章,我突然想到这里没有响应的原因是你的 mysql 和 mysqldump 命令中的“-p”开关。“-p”本身的意思是“提示输入密码”,因此子进程没有响应,因为它们正在等待密码输入。

以防万一其他人遇到这个古老的线程并试图让它为自己工作,这对我来说是一个绊脚石。

于 2021-04-13T20:03:47.403 回答
1

以下是在没有 shell 的情况下运行mysqldump .. | mysql管道的方法:

#!/usr/bin/env python
from subprocess import Popen, PIPE

mysql = Popen("mysql -h localhost -P 3306 -u root -p mydb2".split(),
              stdin=PIPE, stdout=PIPE)
mysqldump = Popen("mysqldump -h localhost -P 3306 -u root -p mydb".split(),
                  stdout=mysql.stdin)
mysql_stdout = mysql.communicate()[0]
mysqldump.wait()

请参阅如何使用 subprocess.Popen 通过管道连接多个进程?

如果您不需要传递需要复杂(可能不可移植)转义的命令行参数,捕获退出状态,stdout,那么在这里使用 shell 会更简单。

于 2015-02-19T02:10:03.590 回答