2016-06-08 5 views
3

아래의 예제 코드에서는 sandbox.log에 파일 설명자를 열고 하위 프로세스에 stdout으로 제공 한 다음 파일 설명자를 닫지 만 하위 프로세스는 여전히 파일에 쓸 수 있습니다. subprocess.Popen은 파일 설명자를 내부적으로 복제합니까? 파일 디스크립터를 서브 프로세스에 전달한 후에 파일 디스크립터를 닫는 것이 안전합니까?닫힌 파일 설명자는 어떻게됩니까?

% 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

파이썬 2를 사용하고 있습니다. 'popen'의'close_fds' 매개 변수를보십시오. 이러한 이유로 3.2가 기본값으로 변경되었습니다. – cdarke

답변

5

각 프로세스가 파일 기술자의 그것의 자신의 세트가있다 : 참고로

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?") 

, 내가 스크립트로 위의 코드를 실행하는 다음과 같은 결과를 얻었다. 한 프로그램에서 fd를 종료해도 다른 프로그램에는 영향을 미치지 않습니다. 이것은 모든 프로그램이 stdin (0), stdout (1), stderr (2)에 대해 동일한 fd 번호를 사용할 수있는 이유와 쉘 스크립트가 사용 가능한지를 확인하지 않고 fd 3을 열 수있는 이유입니다.

파일 설명자는 close-on-exec 플래그를 설정하여 명시 적으로 금지하지 않는 한 하위 프로세스에서 상속됩니다. 기본적으로 플래그가 없으면 자식 프로세스는 부모의 파일 설명 자의 복사본을 가져옵니다.

+0

감사합니다. 당신의 대답은 아주 계몽적이었습니다. – j0eb

관련 문제