Fabric: работа с cd() во вспомогательных функциях

В Fabric менеджер контекста cd работает как

with cd("dir"):
    run("command")

и команда будет запущена после перехода в каталог dir. Это прекрасно работает, но проблема в том, что используется глобальное состояние. Например, предположим, что у меня есть вспомогательная функция, которая должна использовать cd:

def helper():
    with cd("foo"):
        run("some command")

Если я вызову helper из другой функции, например

def main_function():
    helper()
    ...

это работает нормально. Но если я сделаю что-то вроде

def main_function():
    with cd("bar"):
        helper()

он ломается, потому что помощник run("come command") from теперь запускается из bar/foo, а не только из foo.

Любые советы о том, как обойти это? Я пытался использовать абсолютные пути в компакт-диске, но это не сработало. Я действительно хочу, чтобы контекст cd распространялся только на область действия функции.


person asmeurer    schedule 06.07.2013    source источник
comment
Утверждение, что cd использует глобальное состояние, немного вводит в заблуждение. Он изменяет рабочий каталог, который в любом случае является глобальным состоянием, и неожиданное cd — это только один из нескольких способов, с помощью которых команды, полагающиеся на рабочий каталог, могут сломаться. Если вы хотите обойти это, используйте абсолютные пути.   -  person    schedule 06.07.2013
comment
Хорошо, я вижу, что произошло. Я думал, что абсолютные пути не работают, но мои пути не были полностью абсолютными. В них было ~. Предварительное тестирование показывает, что абсолютные пути действительно работают, если они действительно абсолютны.   -  person asmeurer    schedule 06.07.2013
comment
Может быть, это можно считать ошибкой в ​​​​ткани?   -  person asmeurer    schedule 06.07.2013
comment
@asmeurer, это далеко не ошибка, это так задумано, проверьте пример вложенного компакт-диска в документации   -  person iruvar    schedule 07.07.2013
comment
Я имею в виду, что вещь ~ следует считать ошибкой. Я понимаю, что остальное ожидаемое поведение.   -  person asmeurer    schedule 07.07.2013


Ответы (1)


Таким образом, очевидно, что абсолютные пути работают. Проблема в том, что пути с ~ не работают (они обрабатываются как относительные пути, что ИМХО является ошибкой в ​​ткани), и это было то, что я пытался. Поэтому вам нужно сделать (например, если вы используете бродягу) cd('/home/vagrant/foo').

Вероятно, вы можете обойтись без относительных путей во вложенных контекстных менеджерах.

def func():
    with cd("/home/vagrant/foo"):
        stuff()
        with cd("bar"): # cd /home/vagrant/foo/bar
            more_stuff()

потому что вы точно знаете, что такое текущий рабочий каталог, когда вызываете функцию cd('bar'). Но для cd верхнего уровня, если функция когда-либо может быть вызвана из другой функции (а не только непосредственно из fab), вы должны использовать абсолютные пути.

person asmeurer    schedule 06.07.2013
comment
вы можете использовать os.path.expanduser("~/some_thing"), и это отлично работает, чтобы получить полный путь - person Joran Beasley; 07.07.2013
comment
Разве это не расширит пользователя на моей машине, а не на виртуальном ящике? - person asmeurer; 07.07.2013
comment
о, наверное, попробуй и увидишь... не совсем уверен - person Joran Beasley; 07.07.2013