Spawn подпроцесс, который ожидает консольный ввод без блокировки? - PullRequest
4 голосов
/ 04 февраля 2009

Я пытаюсь выполнить вход в CVS из Python, вызвав процесс cvs.exe. При ручном вызове cvs.exe он выводит сообщение на консоль, а затем ждет, пока пользователь введет пароль.

При вызове с помощью subprocess.Popen я заметил, что вызов блокируется. Код

subprocess.Popen(cvscmd, shell = True, stdin = subprocess.PIPE, stdout = subprocess.PIPE,
    stderr = subprocess.PIPE)

Я предполагаю, что он блокируется, потому что он ожидает ввода, но я ожидал, что вызов Popen вернется немедленно, и тогда я смогу вызвать subprocess.communicate () для ввода действительного пароля. Как я могу добиться такого поведения и избежать блокировки на Popen?

ОС: Windows XP
Python: 2,6
cvs.exe: 1.11

Ответы [ 2 ]

2 голосов
/ 04 февраля 2009
  • Удалить часть shell=True. Ваша оболочка не имеет к этому никакого отношения. Использование shell=True является частой причиной проблем.
  • Использовать список параметров для cmd.

Пример:

cmd = ['cvs', 
       '-d:pserver:anonymous@bayonne.cvs.sourceforge.net:/cvsroot/bayonne', 
       'login']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

Это не блокирует мою систему (мой скрипт продолжает выполняться). Однако, поскольку cvs читает пароль непосредственно из терминала (не из стандартного ввода или вывода), вы не можете просто записать пароль в подпроцесс 'stdin.

Вместо этого вы можете передать пароль как часть спецификации CVSROOT, например:

:pserver:<user>[:<passwd>]@<server>:/<path>

т.е. функция для входа в проект sourceforge:

import subprocess

def login_to_sourceforge_cvs(project, username='anonymous', password=''):
    host = '%s.cvs.sourceforge.net' % project
    path = '/cvsroot/%s' % project
    cmd = ['cvs', 
           '-d:pserver:%s:%s@%s:%s' % (username, password, host, path), 
           'login']
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE, 
                              stdout=subprocess.PIPE
                              stderr=subprocess.STDOUT) 
    return p

Это работает для меня. Вызов

login_to_sourceforge_cvs('bayonne')

Анонимно войдет в cvs проекта Байонна.

0 голосов
/ 05 февраля 2009

Если вы автоматизируете внешние программы, которым требуется ввод, например пароль, лучше всего было бы использовать pexpect .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...