Pexpect ест подсказку bash

Этот ожидаемый скрипт запускает оболочку bash, которая включает приглашение:

#! /usr/bin/env expect

spawn -noecho "bash"

expect "$ "

send "echo 'Hello, "

interact

e.g. user@host:/path/to/working/directory$ echo 'Hello,

Я попытался сделать то же самое с Pexpect:

#! /usr/bin/env python

import pexpect

child = pexpect.spawn('bash')

index = child.expect("\$ ")

child.send("echo 'Hello, ")

child.interact()

Однако он проглатывает подсказку и показывает только echo 'Hello,. Я могу заставить bash перерисовать с помощью child.sendcontrol('l'), но это работает только для некоторых оболочек; dash, например, не поддерживает его.

$ python
Python 2.7.9 (default, Dec 11 2014, 08:58:12) 
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pexpect
>>> pexpect.__version__
'3.2'

person Nathaniel M. Beaver    schedule 04.03.2015    source источник
comment
Установите logfile в sys.stdout, чтобы выводить все на стандартный вывод. send() и sendline() разные. В команде есть незакрытая одинарная кавычка. Используйте expect_exact() для соответствия строке без регулярного выражения.   -  person jfs    schedule 05.03.2015
comment
Уже больше недели нет ответа, поэтому я открываю отчет об ошибке.   -  person Nathaniel M. Beaver    schedule 13.03.2015
comment
github.com/pexpect/pexpect/issues/184   -  person Nathaniel M. Beaver    schedule 13.03.2015
comment
ваши ожидания могут быть неверными, например, я не ожидаю, что что-либо, что произойдет до вызова .interact(), будет напечатано, если не установлено .logfile*.   -  person jfs    schedule 13.03.2015
comment
Параметр child.logfile = sys.stdout действительно отображает подсказку, но имеет побочный эффект удваивания каждого ввода. Установка файла журнала во внешний файл показывает подсказку в этом файле, но не на экране.   -  person Nathaniel M. Beaver    schedule 13.03.2015


Ответы (2)


Это не ошибка, pexpect действительно «подавляет» до тех пор, пока не взаимодействует, как это и предполагалось, он не знает, что вы позже вызовете взаимодействие.

В любом случае. Если вы хотите, чтобы приглашение (и что-нибудь еще) распечатывалось до совпадения, просто напечатайте его:

#! /usr/bin/env python
from __future__ import print_function
import pexpect
child = pexpect.spawn('bash')
index = child.expect_exact("$ ")
print(child.before + child.match, end='')
child.interact()

(Будьте осторожны при сопоставлении $, они есть не во всех подсказках. Если вы собираетесь использовать это для какой-либо переносимости, вам следует позаботиться о принудительной установке PS1 и т. д., пример в функции pexpect.replwrap.bash(): https://github.com/pexpect/pexpect/blob/master/pexpect/replwrap.py#L108-113 )

Прошло очень много времени с тех пор, как я использовал оригинальный tcl/expect, но я, кажется, припоминаю, что он подразумевает дублирование всего вывода дочерней программы в родительский процесс: он всегда дублирует стандартный вывод, поэтому Версия tcl/expect не требует печати перед взаимодействием, чтобы «увидеть» то, что было передано до тех пор, пока не будет вызван interact.

https://github.com/pexpect/pexpect/issues/184#issuecomment-78819460

person jquast    schedule 13.03.2015
comment
Пожалуйста, предоставьте некоторые пояснения. См. Как ответить. - person dbank; 13.03.2015
comment
Я перенес полное объяснение с GitHub. - person Nathaniel M. Beaver; 13.03.2015

Как указал Дж. Ф. Себастьян, есть альтернатива:

#! /usr/bin/env python
import pexpect
import sys
child = pexpect.spawn('bash')
child.logfile_read = sys.stdout
index = child.expect_exact("$ ")
child.interact()
person Nathaniel M. Beaver    schedule 13.03.2015