2012-03-29 114 views
27

我有一些自定義命令。Popen錯誤:[Errno 2]沒有這樣的文件或目錄

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

但是,如果我有一個像deactivate我自己的系統命令,我得到這個錯誤

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 

別說我需要在我的沙箱的virtualenv執行此。

+2

腳本運行時'python'不在'PATH'環境變量中。嘗試設置python的完整路徑,即'/ usr/bin/python'。 – 2012-03-29 23:44:24

+1

你能解釋你想完成什麼嗎?我懷疑你用'subprocess'啓動的子shell沒有「源」virtualenv激活腳本,它不是從父Python進程繼承的(假設這是你運行它的地方)。 – 2012-03-29 23:45:45

回答

82

嘗試在Popen調用中添加一個額外的參數'shell = True'。

+40

爲我工作,但爲什麼? – YMomb 2015-03-11 17:44:27

+0

仍然不起作用 – Woeitg 2016-04-28 13:47:29

+5

@YMomb:'deactivate'是一個shell函數。要運行它,你需要一個shell。儘管嘗試在一個新shell中運行它是沒有意義的(新shell可能不會定義它,直到調用venv/bin/activate,並且如果OP希望通過子進程通常無法修改其父環境取消激活在父shell中設置的當前virtualenv,這與subprocess.call('cd')'提出「沒有這樣的文件或目錄」並且可以使用'shell = True'修復的原因是一樣的,毫無意義。請參閱[爲什麼cd不是程序?](http://unix.stackexchange.com/q/38808/1321) – jfs 2016-05-20 09:32:36

3

你必須給你的程序deactivate的完整路徑,然後它的子進程模塊應該能夠找到它。

0

我產卵子過程那樣:

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) 

我不使用子因爲Python 2.5不支持它。我不得不使用完整路徑來使其工作,我想你也必須使用自定義命令的完整路徑。

17

只是一個說明。 shell=True很可能是o.p.的正確解決方案,因爲它們沒有犯下以下錯誤,但是如果你沒有將它的可執行文件從其參數中分離出來,你也可以得到「No such file or directory」錯誤。

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 

沒有shell=True,POPEN預計可執行是args來第一元件,這就是爲什麼它失敗,不存在「呼應1」可執行文件。添加shell=True會調用您的系統shell並將args的第一個元素傳遞給shell。即對於Linux,Popen(['echo 1'], shell=True)相當於Popen('/bin/sh', '-c', 'echo 1'),這比您可能需要的開銷更大。有關shell=True實際上有用的情況,請參見Popen() documentation

+0

如果忘記在字符串文字之間插入逗號,則會發生此版本的錯誤,因爲Python將連接它們:'sp.Popen(['echo''1'])#FAILS' – 2017-06-19 17:08:42

相關問題