使用子进程获取输出
Using subprocess to get output
使用 subprocess 模块如何让下面的命令起作用?
isql -v -b -d, DSN_NAME "DOMAIN\username" password <<<
"SELECT column_name, data_type
FROM database_name.information_schema.columns
WHERE table_name = 'some_table';"
当我 运行 在 bash shell 中时,此命令完美运行,但当 运行 在 [=43] 中运行时,我无法使其运行=].我正在尝试从 Python 中执行此操作,因为我需要能够修改查询并获取不同的结果集,然后在 Python 中处理它们。由于各种原因,我不能使用一个很好的 Python 数据库连接器,这让我尝试通过管道从 isql 输出。
我的代码目前看起来类似于以下内容:
bash_command = '''
isql -v -b -d, DSN_NAME "DOMAIN\username" password <<<
"SELECT column_name, data_type
FROM database_name.information_schema.columns
WHERE table_name = 'some_table';"
'''
process = subprocess.Popen(bash_command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = process.communicate()
但是我尝试了很多变体:
- 将整个命令用作字符串或字符串列表。
- 使用 check_output 与 Popen。
- 使用 communicate() 尝试将查询发送到 isql 命令或使用 heredoc 将查询作为命令字符串的一部分。
- 使用 shell = 正确与否。
- 指定 /bin/bash 或使用默认值 /bin/sh。
- 许多不同的引用和转义模式。
以及上面的几乎所有排列。
在任何情况下我都不会收到我要查找的查询的输出。我很确定命令没有按原样发送到 shell 但我不知道发送到 shell.
的是什么
我觉得这应该很简单,向 shell 发送命令并取回输出,但我无法让它工作。我什至看不到正在向 shell 发送什么命令,即使使用 pdb。
尝试一下:
import shlex
from subprocess import Popen, PIPE, STDOUT
sql_statement = '''"SELECT column_name, data_type
FROM database_name.information_schema.columns
WHERE table_name = 'some_table';"'''
isqlcommand = 'isql -v -b -d, DSN_NAME "DOMAIN\username" password'
isqlcommand_args = shlex.split(isqlcommand)
process = Popen(isqlcommand_args, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
output = process.communicate(input=sql_statement)[0]
print output
这里的想法是将 here-string 重定向与 isql 命令执行分开。此示例将通过 process.communicate()
将 here-string 通过管道传输到 process
的标准输入中。我还使用 shlex.split()
来标记命令及其参数。
编辑:在查看 J.F 的评论后删除了 Shell=True
。塞巴斯蒂安
shell=True
使 subprocess
默认使用 /bin/sh
。 <<< "here-string"
是 bash 主义;通过 executable='/bin/bash'
:
>>> import subprocess
>>> subprocess.call(u'cat <<< "\u0061"', shell=True)
/bin/sh: 1: Syntax error: redirection unexpected
2
>>> subprocess.call(u'cat <<< "\u0061"', shell=True, executable='/bin/bash')
a
0
您还应该使用原始字符串文字来避免转义反斜杠:"\u0061" == r"\u0061" != u"\u0061"
:
>>> subprocess.call(r'cat <<< "\u0061"', shell=True, executable='/bin/bash')
\u0061
0
虽然这里不需要 shell=True
。您可以使用 process.communicate(input=input_string)
:
将输入作为字符串传递
>>> process = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> process.communicate(br"\u0061")
('\u0061', None)
结果可能如下所示:
#!/usr/bin/env python
import shlex
from subprocess import Popen, PIPE
cmd = shlex.split(r'isql -v -b -d, DSN_NAME "DOMAIN\username" password')
process = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, errors = process.communicate(
b"SELECT column_name, data_type "
b"FROM database_name.information_schema.columns "
b"WHERE table_name = 'some_table';")
使用 subprocess 模块如何让下面的命令起作用?
isql -v -b -d, DSN_NAME "DOMAIN\username" password <<<
"SELECT column_name, data_type
FROM database_name.information_schema.columns
WHERE table_name = 'some_table';"
当我 运行 在 bash shell 中时,此命令完美运行,但当 运行 在 [=43] 中运行时,我无法使其运行=].我正在尝试从 Python 中执行此操作,因为我需要能够修改查询并获取不同的结果集,然后在 Python 中处理它们。由于各种原因,我不能使用一个很好的 Python 数据库连接器,这让我尝试通过管道从 isql 输出。
我的代码目前看起来类似于以下内容:
bash_command = '''
isql -v -b -d, DSN_NAME "DOMAIN\username" password <<<
"SELECT column_name, data_type
FROM database_name.information_schema.columns
WHERE table_name = 'some_table';"
'''
process = subprocess.Popen(bash_command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
output, error = process.communicate()
但是我尝试了很多变体:
- 将整个命令用作字符串或字符串列表。
- 使用 check_output 与 Popen。
- 使用 communicate() 尝试将查询发送到 isql 命令或使用 heredoc 将查询作为命令字符串的一部分。
- 使用 shell = 正确与否。
- 指定 /bin/bash 或使用默认值 /bin/sh。
- 许多不同的引用和转义模式。
以及上面的几乎所有排列。
在任何情况下我都不会收到我要查找的查询的输出。我很确定命令没有按原样发送到 shell 但我不知道发送到 shell.
的是什么我觉得这应该很简单,向 shell 发送命令并取回输出,但我无法让它工作。我什至看不到正在向 shell 发送什么命令,即使使用 pdb。
尝试一下:
import shlex
from subprocess import Popen, PIPE, STDOUT
sql_statement = '''"SELECT column_name, data_type
FROM database_name.information_schema.columns
WHERE table_name = 'some_table';"'''
isqlcommand = 'isql -v -b -d, DSN_NAME "DOMAIN\username" password'
isqlcommand_args = shlex.split(isqlcommand)
process = Popen(isqlcommand_args, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
output = process.communicate(input=sql_statement)[0]
print output
这里的想法是将 here-string 重定向与 isql 命令执行分开。此示例将通过 process.communicate()
将 here-string 通过管道传输到 process
的标准输入中。我还使用 shlex.split()
来标记命令及其参数。
编辑:在查看 J.F 的评论后删除了 Shell=True
。塞巴斯蒂安
shell=True
使 subprocess
默认使用 /bin/sh
。 <<< "here-string"
是 bash 主义;通过 executable='/bin/bash'
:
>>> import subprocess
>>> subprocess.call(u'cat <<< "\u0061"', shell=True)
/bin/sh: 1: Syntax error: redirection unexpected
2
>>> subprocess.call(u'cat <<< "\u0061"', shell=True, executable='/bin/bash')
a
0
您还应该使用原始字符串文字来避免转义反斜杠:"\u0061" == r"\u0061" != u"\u0061"
:
>>> subprocess.call(r'cat <<< "\u0061"', shell=True, executable='/bin/bash')
\u0061
0
虽然这里不需要 shell=True
。您可以使用 process.communicate(input=input_string)
:
>>> process = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> process.communicate(br"\u0061")
('\u0061', None)
结果可能如下所示:
#!/usr/bin/env python
import shlex
from subprocess import Popen, PIPE
cmd = shlex.split(r'isql -v -b -d, DSN_NAME "DOMAIN\username" password')
process = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
output, errors = process.communicate(
b"SELECT column_name, data_type "
b"FROM database_name.information_schema.columns "
b"WHERE table_name = 'some_table';")