2016-06-08 111 views
3

在下面的示例代碼中,我們打開一個文件描述符到sandbox.log,將其作爲stdout提供給子進程,然後關閉文件描述符,但子進程仍然可以寫入該文件。是subprocess.Popen內部複製文件描述符?將文件描述符傳遞給子進程後關閉它是否安全?關閉文件描述符是怎麼回事?

import subprocess 
import os 
import time 


print 'create or clear sandbox.log' 
subprocess.call('touch sandbox.log', shell=True) 
subprocess.call('echo "" > sandbox.log', shell=True) 

print 'open the file descriptor' 
fd = os.open('sandbox.log', os.O_WRONLY) 

command = 'sleep 10 && echo "hello world"' 
print 'run the command' 
p = subprocess.Popen(command, stdout=fd, stderr=subprocess.STDOUT, shell=True) 

os.close(fd) 

try: 
    os.close(fd) 
except OSError: 
    print 'fd is already closed' 
else: 
    print 'fd takes some time to close' 

if p.poll() is None: 
    print 'p isnt finished, but fd is closed' 

p.wait() 
print 'p just finished' 

with open('sandbox.log') as f: 
    if any('hello world' in line for line in f): 
     raise Exception("There's text in sandbox.log. Whats going on?") 

僅供參考,我得到了下面的輸出運行上面的代碼的腳本:

% python test_close_fd.py 
create or clear sandbox.log 
open the file descriptor 
run the command 
fd is already closed 
p isnt finished, but fd is closed 
p just finished 
Traceback (most recent call last): 
    File "test_close_fd.py", line 34, in <module> 
    raise Exception("There's text in sandbox.log. Whats going on?") 
Exception: There's text in sandbox.log. Whats going on? 
+0

您正在使用Python 2的外觀。查看'close_fds'參數到'Popen'。由於這些原因,默認情況下更改爲3.2。 – cdarke

回答

5

每個進程都有自己的一套文件描述符。在一個程序中關閉一個fd不會影響另一個程序。這就是爲什麼每個程序都可以爲stdin(0),stdout(1)和stderr(2)使用相同的fd號碼,以及爲什麼shell腳本通常只需打開fd 3而不必檢查它是否可用。

文件描述符被子進程繼承,除非你明確地通過設置close-on-exec標誌來阻止它。默認情況下,如果沒有該標誌,子進程將獲得父文件描述符的副本。

+0

謝謝約翰。你的回答非常有啓發性。 – j0eb

相關問題