2015-04-22 2 views
1

У меня есть подпроцесс бегущегопитона подпроцесс вставки команд внутри запущенного подпроцесс

cmd="bin/candc --models models" 
subprocess.check_output('{} | tee /dev/stderr'.format(cmd), shell=True,cwd=os.path.abspath('candc')) 

и я хочу, чтобы иметь возможность вставить дополнительные команды, которые отражаются только в настоящее время работает подпроцессом.
Обратите внимание, что должен быть параметр cwd=os.path.abspath('candc'), чтобы подпроцесс вызывался извне двоичной папки, иначе он не будет работать.
C&C - это библиотека НЛП, и то, что она на самом деле собирается сделать, - это разобрать данное предложение. Я хочу иметь возможность передать предложение подпроцессу. как я могу это сделать ?

+2

Почему вы подразумеваете под «вставить больше команд»? Вы хотите передать команды на стандартный ввод 'candc'? – abarnert

+0

есть. когда этот подпроцесс запущен, он находится в среде candc и ожидает получения предложения. поэтому я просто хочу передать любое предложение. – mid

+0

Существует около 30 разных вещей под названием 'candc', поэтому я не знаю, какой из них вы используете; это поможет поставить ссылку на вопрос. Но важная часть: имеет ли она интерактивное приглашение, которое вы хотите использовать в интерактивном режиме (например, вы не знаете, что отправить или, по крайней мере, когда отправить следующее, до получения ответа/подсказки) ? – abarnert

ответ

3

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


Если вы можете пройти все команды сразу, как одна большая строка (предположительно присоединился к новой строкой), вы можете сделать это с параметром input, как показано в примерах в check_output документы:

cmd="bin/candc --models models" 
commands="""first candc command 
second candc command 
third candc command 
""" 
subprocess.check_output('{} | tee /dev/stderr'.format(cmd), shell=True, 
         cwd=os.path.abspath('candc'), 
         input=commands) 

Если это Python 3.x, вы также должны использовать закодированные байты для commands или добавить universal_newlines=True, чтобы сделать check_output сделать это за вас. Если ваши команды являются чистыми ASCII, первое проще; просто измените эту строку на commands = b"""….

Если это версия с достаточно старыми версиями (я думаю, это означает 2.6/3.2, но я не уверен, проверьте документы, связанные выше), параметр input еще не существует. В этом случае, у вас есть три варианта:

  • Install subprocess32 от PyPI, которого Backports новой версии библиотеки для более старых версий Python.
  • Посмотрите, как current source обрабатывает аргумент input и выполняет то же самое самостоятельно.
  • Popen.communicate принял аргумент input до check_output, поэтому вы можете просто создать Popen и позвонить по нему communicate.

Последний, по сути, просто более простой вариант второго ... но это намного проще. На самом деле, это всего лишь два лайнера, если вам не нужны все дополнительные сложности обработки тайм-аутов и делать что-то с выходом и так далее:

p = subprocess.Popen('{} | tee /dev/stderr'.format(cmd), shell=True, 
        cwd=os.path.abspath('candc'), stdin=PIPE) 
p.communicate(commands) 

Если вам нужно отправить команды в интерактивном режиме (дождитесь ответа до отправки следующего), то check_output не может этого сделать. Это всего лишь удобная обертка вокруг объекта Popen. Вместо этого вы захотите создать объект Popen явно, затем выполните p.stdin.write и p.stdout.read, чтобы установить связь с ним.

Например, быстрый & грязная версия может быть:

p = subprocess.Popen('{} | tee /dev/stderr'.format(cmd), shell=True, 
        cwd=os.path.abspath('candc'), 
        stdin=PIPE, stdout=PIPE) 
for command in commands.splitlines(): 
    p.stdout.readline() # read and ignore a prompt 
    p.stdin.write(command + '\n') 
rc = p.wait() 
if rc: raise SomeException() # this is the check in check_output 

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

В целом, это может быть очень сложно. (Сам Python не понял этого в функции communicate до 3.2 или 3.3 ...) Особенно, если вы не понимаете, что говорят документы с блокировкой выходного канала. Поэтому, если это действительно то, что вам нужно, вы можете захотеть использовать стороннюю библиотеку, созданную для запуска интерактивных программ командной строки, например pexpect, вместо того, чтобы делать это самостоятельно.

+0

было бы полезно, если бы это сработало. делая то, что вы предложили, я получаю этот erorr: 'TypeError: __init __() получил неожиданный аргумент ключевого слова 'input'' – mid

+0

@mid: если вы проверите связанные документы, я расскажу вам, какая версия Python добавила каждую функцию-оболочку и каждый аргумент этой обертке. Или, если вы сообщите нам, какую версию Python вы используете, я могу проверить это. – abarnert

+0

Я предполагаю, что из-за python 2.7 этот «ввод» является неожиданным. – mid

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