Это мой код ткани:
from fabric import Connection, task
server = Connection(host="[email protected]:22", connect_kwargs={"password": "mypassword"})
@task
def dostuff(somethingmustbehere):
server.run("uname -a")
Этот код работает отлично. Когда я выполняю fab dostuff
он делает то, что я хочу, чтобы он делал.
Когда я удаляю somethingmustbehere
однако, я получаю это сообщение об ошибке:
raise TypeError("Tasks must have an initial Context argument!")
TypeError: Tasks must have an initial Context argument!
Я никогда не определял somethingmustbehere
любом месте моего кода. Я просто вложил его, и ошибка исчезла, и все работает. Но почему? Что это за переменная? Зачем мне это нужно? Почему это так важно? И если это так важно, почему он может быть пустым? Я действительно потерялся здесь. Да, это работает, но я не могу запустить код, который я не понимаю. Это сводит меня с ума. :-)
Имейте в виду, что я говорю о версии Python 3 (!) Fabric! Версия Fabric - 2.4.0
Чтобы иметь возможность запускать @task
вам нужен аргумент контекста. Fabric использует invoke task()
который ожидает увидеть объект контекста. Обычно мы ctx
переменную c
или ctx
(которую я всегда использую, чтобы сделать ее более понятной). Я не предпочитаю использовать c
потому что я обычно использую его для подключения
Проверьте эту строку в github из invoke package repo, вы увидите, что она вызывает исключение, если аргумент контекста отсутствует, но это не объясняет почему!
Чтобы узнать больше о объекте Контекста, что он и зачем он нам нужен, вы можете прочитать следующее на сайте pyinvoke:
Кроме того, что же это за контекст? Общей задачей задач-бегунов является передача "глобальных" данных - значений, загружаемых из файлов конфигурации или других векторов конфигурации, заданных с помощью флагов CLI, сгенерированных в "задачах настройки" и т.д.
Некоторые библиотеки (например, Fabric 1.x) реализуют это с помощью атрибутов на уровне модуля, что делает тестирование сложным и подверженным ошибкам, ограничивает параллелизм и увеличивает сложность реализации.
Invoke инкапсулирует состояние в явные объекты контекста, передаваемые задачам при их выполнении. Контекст - это основная конечная точка API, предлагающая методы, которые соответствуют текущему состоянию (например, Context.run), а также доступ к этому состоянию.
Проверьте эти обе ссылки:
Честно говоря, я потратил много времени на выяснение, что такое контекст, и почему мой код не будет работать без него. Но в какой-то момент я просто сдался и начал использовать, чтобы мой код работал без ошибок.