2013-05-13 119 views
22

我正在使用子進程來調用另一個程序並將其返回值保存到一個變量。重複這個過程,在一個循環中,經過了幾十萬次的程序崩潰並出現以下錯誤:Python子進程:太多打開文件

Traceback (most recent call last): 
    File "./extract_pcgls.py", line 96, in <module> 
    SelfE.append(CalSelfEnergy(i)) 
    File "./extract_pcgls.py", line 59, in CalSelfEnergy 
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
    File "/usr/lib/python3.2/subprocess.py", line 745, in __init__ 
    restore_signals, start_new_session) 
    File "/usr/lib/python3.2/subprocess.py", line 1166, in _execute_child 
    errpipe_read, errpipe_write = _create_pipe() 
OSError: [Errno 24] Too many open files 

不知道如何來解決這個問題,非常感謝!從意見提供

代碼:

cmd = "enerCHARMM.pl -parram=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1]) 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 
out, err = p.communicate() 
+1

Communicate()關閉管道,所以這不是你的問題。最後,Popen()只是當你用盡管道時碰巧運行的命令......問題可能在代碼中的其他地方,其他文件保持打開狀態。我注意到「SelfE.append」...你打開其他文件並將它們保存在列表中嗎? – tdelaney 2013-05-13 17:38:17

回答

10

我想這個問題是由於這樣的事實,我正在處理具有子流程的打開文件:

cmd = "enerCHARMM.pl -par param=x,xtop=topology_modified.rtf,xpar=lipid27_modified.par,nobuildall -out vdwaals {0}".format(cmtup[1]) 
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) 

這裏cmd可變ble包含剛創建但未關閉的文件的名稱。然後subprocess.Popen在該文件上調用系統命令。多次執行此操作後,程序崩潰並顯示該錯誤消息。

所以我從中學到的消息是

Close the file you have created, then process it

感謝

3

您可以嘗試提高操作系統的打開文件限制:

ulimit -n 2048

+4

實際上,該命令不會超出在/ etc/security/limits.conf中設置的限制。爲了提高它,你需要在這個文件中放置類似這些'* soft nofile 4096' /'* hard nofile 4096'的行(用你自己的值替換'4096')。 – 2013-05-13 17:54:50

+1

昨天進入這個問題,我不得不編輯'/ etc/security/limits.conf'並通過ubuntu中的'ulimit -n'提高限制來克服這個錯誤。 – 2018-02-21 15:55:40

0

打開文件中的子進程。它阻止了通話。

ss=subprocess.Popen(tempFileName,shell=True) 
ss.communicate() 
15

在Mac OSX(酋長)查看當前配置:

#ulimit -a 
core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
file size    (blocks, -f) unlimited 
max locked memory  (kbytes, -l) unlimited 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 256 
pipe size   (512 bytes, -p) 1 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 709 
virtual memory   (kbytes, -v) unlimited 

打開的文件值爲10K:

#ulimit -Sn 10000 

驗證結果:

#ulimit -a 

core file size   (blocks, -c) 0 
data seg size   (kbytes, -d) unlimited 
file size    (blocks, -f) unlimited 
max locked memory  (kbytes, -l) unlimited 
max memory size   (kbytes, -m) unlimited 
open files      (-n) 10000 
pipe size   (512 bytes, -p) 1 
stack size    (kbytes, -s) 8192 
cpu time    (seconds, -t) unlimited 
max user processes    (-u) 709 
virtual memory   (kbytes, -v) unlimited 
4

Popen()創建的子進程可以從父進程繼承打開的文件描述符(有限資源)。在POSIX上使用close_fds=True(自Python 3.2以來默認),以避免它。另外,"PEP 0446 -- Make newly created file descriptors non-inheritable" deals with some remaining issues (since Python 3.4)

+0

我不認爲這是有效的,至少在所有情況下。我在1024打開文件限制的系統上生成了1200個睡眠衍生進程(Ubuntu上的默認設置),即使使用close_fds = True,它也會發生爆炸。所以我覺得除此之外還有更多。因爲無論如何,你仍然在打開的進程中超過限制,並且這隻有在你認爲問題在於留下打開的文件描述符的完成進程時纔有效。 – Sensei 2016-10-13 16:51:12

+0

@Sensei它確實有效:在父文件中打開文件(確保文件系統是可繼承的),然後用'close_fds = False'產生子進程(兩者都是舊Python版本的默認版本,請點擊鏈接)。看看你會多快得到錯誤。顯然'close_fds'不能阻止一般情況下的錯誤:你甚至不需要產生一個新的進程來獲取它。 – jfs 2016-10-13 20:04:12

+0

除了它不。我運行了一個簡單的for循環,並生成足夠的子進程來達到操作系統的限制。我用close_fds = True做了這個。它沒有影響。我可能是錯誤的爲什麼,但我的猜測是,這種解決方案只適用於產卵幾個子過程,並從不清理描述符。在這種情況下,這個說法是有道理的,但是如果你真的打算一次產生並運行這麼多的進程,我不會看到它的工作。 – Sensei 2016-10-14 15:55:26

2

正如其他人所指出的,提高的/etc/security/limits.conf極限,也文件描述符是一個問題,對我個人,所以我也

sudo sysctl -w fs.file-max=100000 

後再加fs.file線-max = 100000 /etc/sysctl.conf文件,如果你想確保你的進程不會受別的(這是我的)(用sysctl -p重新加載)

此外,使用

cat /proc/{process id}/limits 

找到了解你的過程的實際限制是什麼,對於我來說,運行python腳本的軟件也應用了它的極限,它已經覆蓋了系統範圍的設置。

在解決了此錯誤的特定問題並希望它可以幫助某人後發佈此答案。