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") от помощника сега се изпълнява от bar/foo вместо само от foo.

Някакви съвети как да заобиколите това? Опитах да използвам абсолютни пътеки в cd, но това не проработи. Това, което наистина искам, е контекстът 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, далеч не е грешка, това е проектирано, проверете пример за вложен cd в документацията   -  person iruvar    schedule 07.07.2013
comment
Искам да кажа, че ~ нещото трябва да се счита за грешка. Разбирам, че останалото е очаквано поведение.   -  person asmeurer    schedule 07.07.2013


Отговори (1)


Така че очевидно абсолютните пътища работят. Проблемът е, че пътеките с ~ не работят (те се третират като относителни пътеки, което IMHO е грешка в тъканта) и това беше, което опитвах. Така че трябва да направите (например, ако използвате vagrant) cd('/home/vagrant/foo').

Вероятно можете да се измъкнете с относителни пътища във вложените контекстни мениджъри

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

защото знаете точно коя е текущата работна директория, когато извикате cd('bar'). Но за cds от най-високо ниво, ако функцията някога може да бъде извикана от друга функция (не само директно от 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