使用子进程获取 pv 输出
Getting pv output with subprocess
我正在编写一个脚本来自动在 MySQL 中导入数据库。我正在尝试编写代码以在导入数据库时显示 pv
的输出:
pv = subprocess.Popen(
["pv", "-f", restore_filepath],
bufsize=1,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
universal_newlines=True,
shell=True,
)
subprocess.Popen(
[
"mysql",
"-u{}".format(db_user),
"-p{}".format(db_pass),
db_name,
],
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
stdin=pv.stdout,
)
for line in pv.stderr:
print("hello")
sys.stdout.write("\r" + line.rstrip("\n"))
sys.stdout.flush()
这是基于 中的代码,但它对我不起作用。 hello
甚至从未被打印出来,即使我注释掉 for 循环中的其他行 - for line in pv.stderr
正在阻塞,我不知道为什么。它永远不会解锁,所以即使进程完成,程序仍然卡住 - 我必须杀死它。
我做错了什么导致 for line in pv.stderr
阻塞?
When shell=True,args[0]
是要执行的命令,args[1:]
是传递给sh
的参数。您希望将 -p
和 restore_filepath
传递给 pv
而不是 sh
。所以使用shell=False
。您的另一个 subprocess.Popen
电话也是如此。
由于 shell=True
,pv
未收到任何参数,因此挂起,因为它仍在等待文件名。所以再次,解决方案是使用 shell=False
.
另请注意,当 replacing a shell pipeline 时,您应该关闭第一个进程的 stdout
,以允许它在第二个进程存在的情况下接收 SIGPIPE。这允许一些程序(那些处理 SIGPIPE 的程序)在管道损坏时更优雅地退出。
pv = subprocess.Popen(
["pv", "-f", restore_filepath],
shell=False, # optional, since this is the default
bufsize=1,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
universal_newlines=True,
)
mysql = subprocess.Popen(
["mysql",
"-u{}".format(db_user),
"-p{}".format(db_pass),
db_name],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
stdin=pv.stdout,
)
pv.stdout.close() # Allow pv to receive a SIGPIPE if mysql exits.
for line in pv.stderr:
print("hello")
sys.stdout.write("\r" + line.rstrip("\n"))
sys.stdout.flush()
我正在编写一个脚本来自动在 MySQL 中导入数据库。我正在尝试编写代码以在导入数据库时显示 pv
的输出:
pv = subprocess.Popen(
["pv", "-f", restore_filepath],
bufsize=1,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
universal_newlines=True,
shell=True,
)
subprocess.Popen(
[
"mysql",
"-u{}".format(db_user),
"-p{}".format(db_pass),
db_name,
],
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
stdin=pv.stdout,
)
for line in pv.stderr:
print("hello")
sys.stdout.write("\r" + line.rstrip("\n"))
sys.stdout.flush()
这是基于 hello
甚至从未被打印出来,即使我注释掉 for 循环中的其他行 - for line in pv.stderr
正在阻塞,我不知道为什么。它永远不会解锁,所以即使进程完成,程序仍然卡住 - 我必须杀死它。
我做错了什么导致 for line in pv.stderr
阻塞?
When shell=True,args[0]
是要执行的命令,args[1:]
是传递给sh
的参数。您希望将 -p
和 restore_filepath
传递给 pv
而不是 sh
。所以使用shell=False
。您的另一个 subprocess.Popen
电话也是如此。
由于 shell=True
,pv
未收到任何参数,因此挂起,因为它仍在等待文件名。所以再次,解决方案是使用 shell=False
.
另请注意,当 replacing a shell pipeline 时,您应该关闭第一个进程的 stdout
,以允许它在第二个进程存在的情况下接收 SIGPIPE。这允许一些程序(那些处理 SIGPIPE 的程序)在管道损坏时更优雅地退出。
pv = subprocess.Popen(
["pv", "-f", restore_filepath],
shell=False, # optional, since this is the default
bufsize=1,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
universal_newlines=True,
)
mysql = subprocess.Popen(
["mysql",
"-u{}".format(db_user),
"-p{}".format(db_pass),
db_name],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
stdin=pv.stdout,
)
pv.stdout.close() # Allow pv to receive a SIGPIPE if mysql exits.
for line in pv.stderr:
print("hello")
sys.stdout.write("\r" + line.rstrip("\n"))
sys.stdout.flush()