Я хочу запустить команду, предлагающую мне ввести да / нет, да / нет или что-то еще. Если я просто запустил команду local("my_command")
, она остановится и попросит меня ввести данные. Когда я печатаю то, что нужно, скрипт продолжает работать. Как я могу автоматически ответить на запрос?
Как автоматически отвечать на запросы с помощью ткани Python?
Ответы (6)
Начиная с версии 1.9
, Fabric включает способ управления этим должным образом.
В разделе о подсказках документации Fabric говорится:
Словарь подсказок позволяет пользователям управлять интерактивными подсказками. Если ключ в словаре найден в стандартном потоке вывода команды, Fabric автоматически ответит соответствующим значением словаря.
Вы должны иметь возможность заставить Fabric автоматически отвечать на такие запросы:
with settings(prompts={'Do you want to continue [Y/n]? ': 'Y'}):
run('apt-get update')
run('apt-get upgrade')
NameError: global name 'settings' is not defined
- person rofls; 28.07.2016
.endswith
для своей проверки, поэтому убедитесь, что вы включили завершающие пробелы в строке, которую вы используете в качестве ключа в словаре prompts
.
- person Christian Long; 21.11.2016
local()
? Я попробовал что-то простое, например with settings(prompts={'Continue? ': 'Y'}): local('read -p "Continue? " var', capture=True)
, и оно было заблокировано в командной строке. Обновление: похоже, что вход все еще был подключен к консоли :(
- person haridsv; 17.05.2017
local
- это просто простая оболочка поверх Popen
, поэтому это не сработает. Думаю, нам нужно использовать pexpect
.
- person haridsv; 17.05.2017
Я использовал простые эхо-каналы, чтобы отвечать на запросы с помощью Fabric.
run('echo "yes\n"| my_command')
yes
: run("yes | my_command")
- person Bob Nadler; 29.07.2014
yes
!
- person benzkji; 07.02.2020
Примечание: этому ответу несколько лет, и в то же время в Fabric есть (что интересно) реализация этого. См. Ответ @ timothée-jeannin ниже.
См. https://stackoverflow.com/a/10007635/708221
pip install fexpect
from ilogue.fexpect import expect, expecting, run
prompts = []
prompts += expect('What is your name?','John')
prompts += expect('Are you at stackoverflow?','Yes')
with expecting(prompts):
run('my_command')
Fexpect добавляет ответ на запросы к ткани с использование pexpect
Чтобы немного расширить отличный ответ Тимоти, вот код, который Fabric использует при проверке словаря prompts
.
def _get_prompt_response(self):
"""
Iterate through the request prompts dict and return the response and
original request if we find a match
"""
for tup in env.prompts.iteritems():
if _endswith(self.capture, tup[0]):
return tup
return None, None
Fabric использует .endswith
для своей проверки, поэтому убедитесь, что вы включили завершающие пробелы в строке, которую вы используете в качестве ключа в словаре prompts
.
Например - предположим, вы пытаетесь автоматизировать приглашение тестовой базы данных Django.
Введите «да», если вы хотите попробовать удалить тестовую базу данных «test_my_app», или «нет» для отмены:
Все, что нам нужно, - это конец приглашения, чтобы оно было уникальным. Включите конечные пробелы.
django_test_database_prompt = "or 'no' to cancel: "
# won't work without this trailing space ^
with settings(
prompts={django_test_database_prompt : 'yes'}
):
run('%s %s' % (virtualenv_python_path,
test_runner_file_path,
)
)
В Fabric 2.1 это можно сделать с помощью пример автоответа, доступный через пакет вызова (зависимость от Fabric 2.1):
>>> from invoke import Responder
>>> from fabric import Connection
>>> c = Connection('host')
>>> sudopass = Responder(
... pattern=r'\[sudo\] password:',
... response='mypassword\n',
... )
>>> c.run('sudo whoami', pty=True, watchers=[sudopass])
[sudo] password:
root
<Result cmd='sudo whoami' exited=0>
Обратите внимание, что это не ограничивается паролями sudo и может использоваться везде, где у вас есть шаблон для сопоставления и готовый ответ (который может не быть паролем).
Есть пара советов:
pty=True
НЕ необходим, но может быть важен, потому что делает поток более реалистичным. например если у вас было приглашение, ожидающее продолжения ответа да / нет, без него (pty=True
) ваша команда все равно будет выполняться; кроме, ваш выбор / ввод (указанныйresponse
) не будет отображаться как набранный в качестве ответа, как можно было бы ожидать.pattern
, указанный вResponder
, часто может включать пробелы в конце строки, поэтому попробуйте добавить пробелы, еслиwatcher
не соответствует.Согласно примечанию, приведенному в конце документации наблюдателя:
Аргумент шаблона для Responder обрабатывается как регулярное выражение, требующее большей осторожности (обратите внимание, как нам пришлось избегать квадратных скобок в приведенном выше примере), но также предоставляющее больше возможностей.
Так что не забывайте экранировать (используя обратную косую черту) там, где это необходимо.
Помещая это как ответ, хотя это комментарий от @BobNadler
запустить ("да | моя_команда");