使用子进程模块如何使以下命令起作用?
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()
但是我尝试了很多变化:
几乎所有上述的排列。
在任何情况下,我都不会收到我正在寻找的查询的输出。我很确定该命令没有按原样发送到shell,但我无法分辨发送给shell的内容。
我觉得这应该很简单,向shell发送命令并获取输出,但我无法使其工作。即使使用pdb,我甚至无法看到发送到shell的命令。
答案 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';")