2016-06-08 9 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 в одной программе не повлияет на другую программу. Вот почему каждая программа может использовать одни и те же номера fd для stdin (0), stdout (1) и stderr (2), и почему сценарии оболочки обычно могут просто открывать fd 3, не проверяя, доступно ли это.

Дескрипторы файлов наследуются дочерними процессами, если только вы явно не предотвращаете это, установив флаг close-on-exec. По умолчанию без этого флага дочерний процесс получит копии дескрипторов файлов родителя.

+0

Спасибо, Джон. Ваш ответ был очень поучительным. – j0eb