简体   繁体   English

通过子过程获取光伏输出

[英]Getting pv output with subprocess

I am writing a script to automate database imports in MySQL. 我正在编写一个脚本来自动在MySQL中导入数据库。 I'm trying to write code that displays the output of pv as the database is imported: 我正在尝试编写代码,以在导入数据库时​​显示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()

This is based on the code in this question , but it is not working for me. 这是基于此问题中的代码,但对我不起作用。 The hello never even gets printed, even if I comment out the other lines in the for loop - for line in pv.stderr is blocking and I don't know why. hello甚至从来没有被印刷,即使我注释掉其他线路中的for循环- for line in pv.stderr挡住,我不知道为什么。 It never unblocks, so even once the process has completed, the program is still stuck - I have to kill it. 它永远不会畅通无阻,因此即使该过程完成了,该程序仍然会卡住-我必须将其杀死。

What am I doing wrong that is causing for line in pv.stderr to block? 我做错了什么导致for line in pv.stderr中的行阻塞?

When shell=True , args[0] is the command to be executed and args[1:] are arguments passed to sh . 当shell = True时args[0]是要执行的命令,而args[1:]是传递给sh参数。 You want -p and restore_filepath to be passed to pv not sh . 您希望将-prestore_filepath传递给pv而不是sh So use shell=False . 因此,使用shell=False The same goes for your other subprocess.Popen call. 您的其他subprocess.Popen调用也是如此。

Since with shell=True , pv is not receiving any arguments, so it is hanging because it was still waiting for a filename. 由于使用shell=Truepv不接收任何参数,因此它挂起,因为它仍在等待文件名。 So again, the solution is to use shell=False . 同样,解决方案是使用shell=False

Also note when replacing a shell pipeline , you should close stdout on the first process to allow it to receive SIGPIPE if the second process exists. 还要注意,在替换外壳程序管道时 ,如果第二个进程存在,则应在第一个进程上关闭stdout ,以使其能够接收SIGPIPE。 This allows some programs (those that handle SIGPIPE) to more gracefully exit if the pipeline is broken. 如果管道中断,这可以使某些程序(处理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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM