2012-03-29 31 views
27

Mam kilka niestandardowych poleceń.Błąd popen: [Errno 2] Brak takiego pliku lub katalogu

# works 
subprocess.Popen(['python'], stdout=subprocess.PIPE) 

Ale jeśli mam własne poleceń systemowych jak deactivate, otrzymuję ten błąd

Traceback (most recent call last): 
    File "runner2.py", line 21, in <module> 
    main() 
    File "runner2.py", line 18, in main 
    subprocess.Popen(['deactivate',], stdout=subprocess.PIPE) 
    File "/usr/lib/python2.6/subprocess.py", line 633, in __init__ 
    errread, errwrite) 
    File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child 
    raise child_exception 
OSError: [Errno 2] No such file or directory 

nie mówiąc muszę wykonać to pod moim piaskownicy virtualenv.

+2

Być może 'python' nie znajduje się w zmiennej środowiskowej' PATH' podczas działania skryptu. Spróbuj ustawić pełną ścieżkę do Pythona, czyli '/ usr/bin/python'. –

+1

Czy możesz wyjaśnić, co próbujesz osiągnąć? Podejrzewam, że powłoka podrzędna, którą uruchamiasz z 'podprocesorem', nie" pochodzi "ze skryptu aktywacyjnego virtualenv i nie jest dziedziczona z macierzystego procesu Python (zakładając, że jest to miejsce, z którego go uruchamiasz). –

Odpowiedz

82

Spróbuj dodać dodatkowy parametr "shell = True" do połączenia Popen.

+40

Pracowałem dla mnie, ale dlaczego? – YMomb

+0

nadal nie działa – Woeitg

+5

@Momb: 'deactivate' jest funkcją powłoki. Aby go uruchomić, potrzebujesz powłoki. Chociaż nie ma sensu próbować uruchomić go w nowej powłoce (nowa powłoka prawdopodobnie nie będzie tego zdefiniowana, dopóki nie zostanie wywołane 'venv/bin/activate', a dziecko normalnie nie będzie mogło modyfikować swojego środowiska macierzystego, jeśli OP będzie miał nadzieję na dezaktywuj bieżący zestaw virtualenv w powłoce rodzica.To jest ten sam powód, dla którego 'subprocess.call ('cd')' podnosi "Brak takiego pliku lub katalogu" i można go naprawić za pomocą 'shell = True' i byłoby to równie ważne pointless.See [Dlaczego cd nie jest programem?] (http://unix.stackexchange.com/q/38808/1321) – jfs

3

Musisz podać pełną ścieżkę do programu deactivate, a następnie moduł podprocesowy powinien móc go znaleźć.

0

mam tarła podprocesów tak:

SHUTDOWN_CMD = os.path.sep.join(["c:", "windows", "system32", "shutdown.exe"]) 

def abortShutdown(): 
    os.spawnv(os.P_NOWAIT, SHUTDOWN_CMD, 
     [SHUTDOWN_CMD, '/A']) 
    time.sleep(3) 

nie używam podproces od Python 2.5 nie obsługuje. Musiałem użyć ścieżki FULL, aby to działało i domyślam się, że musisz również użyć pełnej ścieżki do własnych poleceń.

17

Tylko notatkę. shell=True było prawdopodobnie właściwym rozwiązaniem dla o.p., ponieważ nie popełnił on następującego błędu, ale możesz również uzyskać błąd "Brak takiego pliku lub katalogu", jeśli nie podzielisz pliku wykonywalnego z jego argumentów.

import subprocess as sp, shlex 
sp.Popen(['echo 1']) # FAILS with "No such file or directory" 
sp.Popen(['echo', '1']) # SUCCEEDS 
sp.Popen(['echo 1'], shell=True) # SUCCEEDS, but extra overhead 
sp.Popen(shlex.split('echo 1')) # SUCCEEDS, equivalent to #2 

Bez shell=True, Popen spodziewa wykonywalny być pierwszy element args, dlatego też nie, nie ma „echo 1” wykonywalny. Dodanie shell=True wywołuje powłokę systemową i przekazuje do niej pierwszy element z args. tj. dla Linux-a, Popen(['echo 1'], shell=True) jest odpowiednikiem Popen('/bin/sh', '-c', 'echo 1'), co oznacza więcej kosztów niż potrzebujesz. Zobacz Popen() documentation dla przypadków, gdy shell=True jest rzeczywiście przydatna.

+0

Ta wersja błędu może wystąpić, jeśli zapomnisz wstawić przecinki między literałami łańcuchowymi, ponieważ Python połączy je: 'sp.Popen (['echo' '1']) # FAILS' –

Powiązane problemy