2013-02-15 3 views
3

У меня проблема с пакетом многопроцессорности Python. Ниже приведен простой пример кода, который иллюстрирует мою проблему.Многопроцессорность Python, ValueError: операция ввода-вывода в закрытом файле

import multiprocessing as mp 
import time 

def test_file(f): 
    f.write("Testing...\n") 
    print f.name 
    return None 

if __name__ == "__main__": 
    f = open("test.txt", 'w') 
    proc = mp.Process(target=test_file, args=[f]) 
    proc.start() 
    proc.join() 

Когда я запустил это, я получаю следующее сообщение об ошибке.

Process Process-1: 
Traceback (most recent call last): 
    File "C:\Python27\lib\multiprocessing\process.py", line 258, in _bootstrap 
    self.run() 
    File "C:\Python27\lib\multiprocessing\process.py", line 114, in run 
    self.target(*self._args, **self._kwargs) 
    File "C:\Users\Ray\Google Drive\Programming\Python\tests\follow_test.py", line 24, in test_file 
    f.write("Testing...\n") 
ValueError: I/O operation on closed file 
Press any key to continue . . . 

Похоже, что когда-то дескриптор файла «потерян» во время создания нового процесса. Может кто-нибудь объяснить, что происходит?

+4

При нажатии на иконку консоли в верхнем левом углу, вы увидите опции меню, чтобы выбрать и скопировать текст. * Пожалуйста, используйте эту функцию для копирования трассировки * в виде текста * в свои сообщения. –

+1

http://stackoverflow.com/questions/1075443/multiprocessing-share-objects-with-file-handle-attribute-between-processes ... вы можете сбросить свой вывод в очередь, и когда все ваши процессы будут завершить, вывести выход из очереди и записать его через основной процесс – pyInTheSky

ответ

7

У меня были подобные проблемы в прошлом. Не уверен, что это сделано в модуле многопроцессорности, или по умолчанию open устанавливает флажок close-on-exec, но я точно знаю, что дескрипторы файлов, открытые в основном процессе, - закрыты в многопроцессорных дочерних элементах.

Очевидная задача - передать имя файла в качестве параметра функции init init дочернего процесса и открыть его один раз в каждом дочернем элементе (при использовании пула) или передать его в качестве параметра целевой функции и открыть/закрыть при каждом вызове. Первый требует использования глобального для хранения дескриптора файла (не очень хорошо) - если кто-то не покажет мне, как избежать этого :) - и последний может понести удар производительности (но может использоваться с multiprocessing.Process напрямую).

Пример бывший:

filehandle = None 

def child_init(filename): 
    global filehandle 
    filehandle = open(filename,...) 
    ../.. 

def child_target(args): 
    ../.. 

if __name__ == '__main__': 
    # some code which defines filename 
    proc = multiprocessing.Pool(processes=1,initializer=child_init,initargs=[filename]) 
    proc.apply(child_target,args) 
+0

Спасибо isedev! Я надеюсь, что подобная проблема не возникает с другими объектами. Вы знаете что-нибудь? – Ray

+0

Не об этом я знаю. – isedev