2015-09-10 3 views
3

Использование модуля подпроцесса, как мне получить следующую команду?Использование подпроцесса для получения вывода

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

Эта команда отлично работает, когда я запускаю его в Баш оболочку, но я не могу заставить его работать при работе внутри 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.
  • Использование связи(), чтобы попытаться отправить запрос команде isql или иметь запрос в составе командной строки с использованием heredoc.
  • Использование оболочки = True или нет.
  • Задание/bin/bash или использование по умолчанию/bin/sh.
  • Много разных цитат и экранов.

И почти каждая перестановка вышеизложенного.

Ни в коем случае я не получаю вывод запроса, который я ищу. Я уверен, что команда не отправляется в оболочку как есть, но я не могу сказать, что отправляется в оболочку.

Я чувствую, что это должно быть довольно просто, отправить команду в оболочку и вернуть ее обратно, но я просто не могу заставить ее работать. Я даже не вижу, какая команда отправляется в оболочку, даже используя pdb.

+0

Проверили вы свой подпроцесс на простые команды, как Ls, Whoami и т.д.? – Sergius

+0

Это запятая намеренно после '-d'? – jfs

+0

@ J.F.Sebastian Да. Его разделитель. –

ответ

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

Идея заключается в том, чтобы отделить здесь струнами Перенаправление от выполнения ISQL команды. В этом примере эта строка будет передана в stdin из process через process.communicate(). Я также использую shlex.split() для tokenize команды и ее аргументов.

Edit: Удалены Shell=True после просмотра комментария от J.F. Sebastian

+0

[не используйте аргумент списка и 'shell = True' на POSIX] (http://bugs.python.org/issue21347). – jfs

+0

use 'subprocess.check_output' – amirouche

+0

Спасибо J.F. Себастьян. Я только что узнал что-то новое. :) –

Смежные вопросы