繁体   English   中英

在Python中,我如何使用subprocess而不是os.system?

[英]In Python, how I do use subprocess instead of os.system?

我有一个Python脚本调用具有各种参数的可执行程序(在此示例中,它是'sqlpubwiz.exe',它是“Microsoft SQL Server数据库发布向导”):

import os

sqlpubwiz = r'"C:\Program Files\Microsoft SQL Server\90\Tools\Publishing\sqlpubwiz.exe"'
server = 'myLocalServer'
database = 'myLocalDatabase'
connection_values = ['server=' + server, 'database=' + database, 'trusted_connection=true']
connection_string = ';'.join(connection_values)
dbms_version = '2000'
sqlscript_filename = 'CreateSchema.sql'

args = [
        sqlpubwiz,
        'script',
        '-C ' + connection_string,
        sqlscript_filename,
        '-schemaonly',
        '-targetserver ' + dbms_version,
        '-f',
]

cmd = ' '.join(args)
os.system(cmd)

这段代码运行正常,但我想养成使用进程的习惯,因为它打算替换os.system。 但是,经过几次尝试失败后,我似乎无法正常工作。

如果转换为使用子进程代替os.system,上面的代码将如何?

import subprocess
p=subprocess.Popen(args, stdout=subprocess.PIPE)
print p.communicate()[0]

它看起来几乎一样。 但路径不应该是“无论路径是什么”。 因为这给了我一个错误。 你想要“带有转义反斜杠的路径”或“r'the path而不转义”。

args的形式也应该是['-arg','args']而不是['arg argsval']。

从可执行文件的名称中删除引号。 在您的示例的第一行,而不是

sqlpubwiz = r'"C:\Program Files\Microsoft SQL Server\90\Tools\Publishing\sqlpubwiz.exe"'

采用:

sqlpubwiz = r'C:\Program Files\Microsoft SQL Server\90\Tools\Publishing\sqlpubwiz.exe'

那是因为你不必逃避任何东西,因为不会涉及shell。

然后只使用subprocess.call(args) (不join args,将它们作为列表传递)

如果要捕获输出( os.system无法执行此操作),请按照 os.system文档进行操作:

result = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
print result

以下是基于Carlos Rendon (和nosklo )帮助和建议的修订代码:

# import os
import subprocess    

sqlpubwiz = r'C:\Program Files\Microsoft SQL Server\90\Tools\Publishing\sqlpubwiz.exe'
server = 'myLocalServer'
database = 'myLocalDatabase'
connection_values = ['server=' + server, 'database=' + database, 'trusted_connection=true']
connection_string = ';'.join(connection_values)
dbms_version = '2000'
sqlscript_filename = 'CreateSchema.sql'       

args = [
            sqlpubwiz,
            'script',
            '-C',
            connection_string,
            sqlscript_filename,
            '-schemaonly',
            '-targetserver',
            dbms_version,
            '-f',
    ]   

# cmd = ' '.join(args)
# os.system(cmd)

subprocess.call(args)

(注意:包含空格的原始参数值需要转换为单独的列表项。)

仅供参考, subprocesslist2cmdline()函数,可以让你看到字符串Popen将使用。

你的版本给出:

'"C:\\Program Files\\Microsoft SQL Server\\90\\Tools\\Publishing\\sqlpubwiz.exe" script "-C server=myLocalServer;database=myLocalDatabase;trusted_connection=true" CreateSchema.sql -schemaonly "-targetserver 2000" -f'

"-C server=myLocalServer;database=myLocalDatabase;trusted_connection=true""-targetserver 2000"附加引号。

格式正确:

args = [
        sqlpubwiz,
        'script',
        '-C', connection_string,
        sqlscript_filename,
        '-schemaonly',
        '-targetserver', dbms_version,
        '-f',
]

得到:

'"C:\\Program Files\\Microsoft SQL Server\\90\\Tools\\Publishing\\sqlpubwiz.exe" script -C server=myLocalServer;database=myLocalDatabase;trusted_connection=true CreateSchema.sql -schemaonly -targetserver 2000 -f'

此外,还有一点,但是将序列(如args不需要变为元组而不是列表是一个好习惯。

请记住,os.system使用shell,所以你必须真正通过

shell=True

到Popen构造函数/调用来正确模拟它。 当然,你可能不需要shell,但它确实存在。

这不是你的问题的直接答案,但我认为它可能会有所帮助。

如果您想要更精细地控制异常处理返回的内容等,您还可以查看pexpect 我已经在我调用的进程不一定退出正常状态信号的情况下使用它,或者我想更多地与它进行交互。 这是一个非常方便的功能。

Windows命令将接受正斜杠'/'来代替路径名中的反斜杠,因此您可以使用前者来避免在命令字符串中转义反斜杠。 不完全是你的问题的答案,但也许有用的知道。

暂无
暂无

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

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