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

时间:2021-12-30 07:09:49

I have a Python script that calls an executable program with various arguments (in this example, it is 'sqlpubwiz.exe' which is the "Microsoft SQL Server Database Publishing Wizard"):

我有一个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)

This code runs properly but I have would like to get into the habit of using subprocess since it is intended to replace os.system. However, after a few failed attempts, I can not seem to get it work properly.

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

How would the above code look like if it was converted to use subprocess in place of os.system?

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

7 个解决方案

#1


5  

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

It would look pretty much the same. But the path should not be r'"whatever the path is"'. Because that gives me an error. You want "the path with escaped backslashes" or r'the path without escaping'.

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

Also args should be of the form ['-arg', 'args'] instead of ['arg argsval'].

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

#2


4  

Remove quotes from the name of the executable. On the first line of your example, instead of

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

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

use:

使用:

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

That's because you don't have to escape anything since a shell won't be involved.

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

Then just use subprocess.call(args) (don't join the args, pass them as a list)

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

If you want to capture the output (os.system can't do it) just follow subprocess documentation:

如果你想捕获输出(os.system不能这样做),只需按照子进程文档:

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

#3


4  

Below is my revised code based on Carlos Rendon (and nosklo) help and suggestions:

以下是基于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)

(Note: The original argument values that contained spaces needed to be converted into separate list items.)

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

#4


4  

FYI, subprocess has a list2cmdline() function that will let you see the string that Popen will be using.

FYI,subprocess有一个list2cmdline()函数,可以让你看到Popen将使用的字符串。

Your version gives:

你的版本给出:

'"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'

with extra quotes around "-C server=myLocalServer;database=myLocalDatabase;trusted_connection=true" and "-targetserver 2000".

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

Properly formatted:

格式正确:

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

gives:

得到:

'"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'

Also, minor point, but it's a good habit to make sequences such as args that don't need to be mutable into tuples instead of lists.

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

#5


0  

This isnt an answer directly to your question but I thought it might be helpful.

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

In case you ever want more granular control over what is returned for exception handling etc, you can also check out pexpect. I have used it in situations where the process I was calling didn't necessarily exit with normal status signals, or I wanted to interact with it more. It's a pretty handy function.

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

#6


0  

Windows commands will accept forward slashes '/' in place of backslashes in pathnames, so you can use the former to avoid escaping backslashes in your command strings. Not exactly an answer to your question, but perhaps useful to know.

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

#7


-1  

Please remember that os.system uses the shell, and so you must really pass

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

shell=True

to the Popen constructor/call to emulate it properly. You may not actually need a shell, of course, but there it is.

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

#1


5  

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

It would look pretty much the same. But the path should not be r'"whatever the path is"'. Because that gives me an error. You want "the path with escaped backslashes" or r'the path without escaping'.

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

Also args should be of the form ['-arg', 'args'] instead of ['arg argsval'].

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

#2


4  

Remove quotes from the name of the executable. On the first line of your example, instead of

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

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

use:

使用:

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

That's because you don't have to escape anything since a shell won't be involved.

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

Then just use subprocess.call(args) (don't join the args, pass them as a list)

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

If you want to capture the output (os.system can't do it) just follow subprocess documentation:

如果你想捕获输出(os.system不能这样做),只需按照子进程文档:

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

#3


4  

Below is my revised code based on Carlos Rendon (and nosklo) help and suggestions:

以下是基于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)

(Note: The original argument values that contained spaces needed to be converted into separate list items.)

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

#4


4  

FYI, subprocess has a list2cmdline() function that will let you see the string that Popen will be using.

FYI,subprocess有一个list2cmdline()函数,可以让你看到Popen将使用的字符串。

Your version gives:

你的版本给出:

'"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'

with extra quotes around "-C server=myLocalServer;database=myLocalDatabase;trusted_connection=true" and "-targetserver 2000".

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

Properly formatted:

格式正确:

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

gives:

得到:

'"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'

Also, minor point, but it's a good habit to make sequences such as args that don't need to be mutable into tuples instead of lists.

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

#5


0  

This isnt an answer directly to your question but I thought it might be helpful.

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

In case you ever want more granular control over what is returned for exception handling etc, you can also check out pexpect. I have used it in situations where the process I was calling didn't necessarily exit with normal status signals, or I wanted to interact with it more. It's a pretty handy function.

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

#6


0  

Windows commands will accept forward slashes '/' in place of backslashes in pathnames, so you can use the former to avoid escaping backslashes in your command strings. Not exactly an answer to your question, but perhaps useful to know.

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

#7


-1  

Please remember that os.system uses the shell, and so you must really pass

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

shell=True

to the Popen constructor/call to emulate it properly. You may not actually need a shell, of course, but there it is.

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