使用子流程获取输出

时间:2015-09-10 19:50:00

标签: python 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中运行它时,这个命令工作正常,但是当我在Python中运行时,我无法使它工作。我正在尝试从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 vs Popen。
  • 使用communic()尝试将查询发送到isql命令,或者使用heredoc将查询作为命令字符串的一部分。
  • 使用shell = True。
  • 指定/ bin / bash或使用默认的/ bin / sh。
  • 许多不同的引用和转义模式。

几乎所有上述的排列。

在任何情况下,我都不会收到我正在寻找的查询的输出。我很确定该命令没有按原样发送到shell,但我无法分辨发送给shell的内容。

我觉得这应该很简单,向shell发送命令并获取输出,但我无法使其工作。即使使用pdb,我甚至无法看到发送到shell的命令。

2 个答案:

答案 0 :(得分:2)

试着试一试:

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命令执行分开。此示例将here-string通过process传递到process.communicate()的标准输入。我也使用shlex.split()来标记命令及其参数。

修改在审核了J.F. Sebastian的评论之后删除了Shell=True

答案 1 :(得分:2)

shell=True默认使subprocess使用/bin/sh<<< "here-string"是一种抨击;通过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';")