【问题标题】:Does the python code executes in orderpython代码是否按顺序执行
【发布时间】:2013-07-15 09:49:08
【问题描述】:

我正在创建一个文件,然后对其进行比较。

我想对在上一步中创建的文件进行比较,但我得到文件不存在的错误。

这是我的代码

os.popen("mysqldump --login-path=server1_mysql -e --opt --skip-lock-tables  --skip-extended-insert -c %s > %s.sql" % (database, filename))
os.popen("diff %s %s > %s" % (weekly, filename, filename+".PATCH"))

【问题讨论】:

    标签: python subprocess diff


    【解决方案1】:

    os.popen is deprecated. Use the subprocess modulesubprocess.call 将阻塞主进程,直到命令完成。您应该检查返回码retval,以防在执行mysqldump 命令时出现错误。在这种情况下,您无法继续使用diff

    import subprocess
    import shlex
    with open("{f}.sql".format(f=filename), 'w') as fout:
        retval = subprocess.call(
            shlex.split(
                """mysqldump --login-path=server1_mysql -e --opt --skip-lock-tables
                --skip-extended-insert -c %s""" % (database, )),
            stdout=fout)
    
    if not retval == 0:
        raise Exception('Error executing command: {r}'.format(r=retval))
    else:
        with open("{f}.PATCH".format(f=filename), 'w') as fout:
            retval = subprocess.call(
                shlex.split("diff {w} {f}".format(w=weekly, f=filename)),
                stdout=fout)
    

    【讨论】:

    • 在这种情况下,communicate 没有任何意义,因此调用proc.wait() 会更简单。但总的来说,是的(赞成)。
    • @torek:是的。谢谢!
    • 哦,我刚才注意到的另一件事:使用 shlex.split 通常很好,但在这种情况下,字符串希望 shell 进行重定向,所以你需要 shell=True 而不需要拆分字符串。或者(比尝试引用 shell 元字符更安全),在 Python 中打开输出文件并在子进程调用中将其作为 stdout= 传递。
    • 谢谢,@torek。很好的保存。
    • 上述语法是否正确,我收到语法错误。我收到IOError: [Errno 2] No such file or directory: 那个文件名不存在,mysql dump 会创建它,我不知道你是怎么做到的
    【解决方案2】:

    os.popen() 一直是deprecated since version 2.6。但是,要使您的代码正常工作,您应该等待第一个进程完成(以及要创建的输出文件),然后再开始第二个进程。

    第一个命令的退出状态可以作为返回的文件对象的close()方法的返回值,所以你可以在继续之前检查一下,即:

    pipe = os.popen("mysqldump --login-path=server1_mysql -e --opt "
                    "--skip-lock-tables  --skip-extended-insert -c %s > %s.sql" % 
                    (database, filename))
    if pipe.close() is None:  # no errors?
        os.popen("diff %s %s > %s" % (weekly, filename, filename+".PATCH"))
    

    【讨论】:

    • 谢谢老兄,只有你的代码有效。这可能并不完美,但确实有效
    • 很高兴听到这个消息,但是您确实应该在某个时候将您的代码转换为使用subprocess.call()——它肯定会更好,而且通常相对更容易使用。
    【解决方案3】:

    一个超级简单的方法是使用忙等待:

    os.popen("mysqldump --login-path=server1_mysql -e --opt --skip-lock-tables  --skip-extended-insert -c %s > %s.sql" % (database, filename))
    while not os.path.isfile(filename):
        sleep(0.05) # or some other interval
    os.popen("diff %s %s > %s" % (weekly, filename, filename+".PATCH"))
    

    编辑:

    小心使用,留下一个竞争条件,因为正在检查的条件只是文件存在,而不是前一个进程已完成写入。

    【讨论】:

    • 忙着等待简单,但没必要;这会导致竞争情况:差异可能会在 mysqldump 启动但在 mysqldump 完成之前启动。
    • 确实如此,这可能有点简单了。我仍然认为学习简单的(old school,如果你愿意的话)解决方案,比如忙着等待是有用的,而且在某些情况下它仍然是必要的。但我同意在这种情况下它不是最理想的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2021-03-16
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多