2009-02-18 2 views
7

Моя программа, как представляется, пропускает файлы. Как я могу узнать, где?Обнаружение ошибок дескриптора файла в python?

В моей программе используются файловые дескрипторы в нескольких разных местах - вывод из дочерних процессов, вызов ctypes API (ImageMagick) открывает файлы, и они копируются.

Он падает в shutil.copyfile, но я уверен, что это не то место, где оно протекает.

Traceback (most recent call last): 
    File "<string>", line 1, in <module> 
    File "C:\Python25\Lib\site-packages\magpy\magpy.py", line 874, in main 
    magpy.run_all() 
    File "C:\Python25\Lib\site-packages\magpy\magpy.py", line 656, in run_all 
    [operation.operate() for operation in operations] 
    File "C:\Python25\Lib\site-packages\magpy\magpy.py", line 417, in operate 
    output_file = self.place_image(output_file) 
    File "C:\Python25\Lib\site-packages\magpy\magpy.py", line 336, in place_image 
    shutil.copyfile(str(input_file), str(self.full_filename)) 
    File "C:\Python25\Lib\shutil.py", line 47, in copyfile 
    fdst = open(dst, 'wb') 
IOError: [Errno 24] Too many open files: 'C:\\Documents and Settings\\stuart.axon\\Desktop\\calzone\\output\\wwtbam4\\Nokia_NCD\\nl\\icon_42x42_V000.png' 
Press any key to continue . . . 
+0

Не совсем ответ, но если вы используете Python 2.5 или новее, загляните в ключевое слово «с», которое может автоматически закрыть файлы для вас, как только вы закончите с ними. –

ответ

3

Посмотрите на выходе из ls -l /proc/$pid/fd/ (подставляя PID вашего процесса, конечно), чтобы увидеть, какие файлы открыты [или, на win32, используйте Process Explorer в список открытых файлов]; затем выясните, где в вашем коде вы их открываете и делаете вызов close(). (Да, сборщик мусора, в конечном счете, закрывает вещи, но он не всегда достаточно быстр, чтобы избежать исхода из fds).

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

+0

Я предполагаю, что это поле win32, с учетом путей c: \ python25. – twk

+0

Сбор мусора: Есть ли у python что-то вроде сборщика циклов в некоторых реализациях js? – 2009-02-18 17:35:12

+0

@Stuart - это GC с циклом с подсчетом отсчетов, но сборщик циклов работает недостаточно часто, чтобы обязательно закрывать объекты без ссылки на объекты до того, как закончится ОЗУ. –

3

Используйте Process Explorer, выберите ваш процесс, Вид-> Вид нижней панели-> Ручки - затем найдите то, что кажется неуместным - обычно много одинаковых или похожих файлов открывают точки к проблеме.

3

lsof -p <process_id> хорошо работает на нескольких UNIX-подобных системах, включая FreeBSD.

+0

Очевидно, что вопрос касается Windows. – Olli

3

У меня были подобные проблемы, закончились файловые дескрипторы во время вызовов subprocess.Popen(). Я использовал следующий сценарий для отладки на то, что происходит:

import os 
import stat 

_fd_types = (
    ('REG', stat.S_ISREG), 
    ('FIFO', stat.S_ISFIFO), 
    ('DIR', stat.S_ISDIR), 
    ('CHR', stat.S_ISCHR), 
    ('BLK', stat.S_ISBLK), 
    ('LNK', stat.S_ISLNK), 
    ('SOCK', stat.S_ISSOCK) 
) 

def fd_table_status(): 
    result = [] 
    for fd in range(100): 
     try: 
      s = os.fstat(fd) 
     except: 
      continue 
     for fd_type, func in _fd_types: 
      if func(s.st_mode): 
       break 
     else: 
      fd_type = str(s.st_mode) 
     result.append((fd, fd_type)) 
    return result 

def fd_table_status_logify(fd_table_result): 
    return ('Open file handles: ' + 
      ', '.join(['{0}: {1}'.format(*i) for i in fd_table_result])) 

def fd_table_status_str(): 
    return fd_table_status_logify(fd_table_status()) 

if __name__=='__main__': 
    print fd_table_status_str() 

Вы можете импортировать этот модуль и вызвать fd_table_status_str() войти статус дескриптора файла таблицы в различных точках в вашем коде.

Также убедитесь, что экземпляры subprocess.Popen уничтожены. Сохранение ссылок экземпляров Popen в Windows предотвращает запуск GC. И если экземпляры сохранены, связанные каналы не закрываются. Больше информации here.

+0

«Кроме того, убедитесь, что экземпляры subprocess.Popen уничтожены. Сохранение ссылок экземпляров Popen в Windows предотвращает запуск GC. И если экземпляры сохранены, связанные с ними каналы не закрываются. Дополнительная информация» - это особая причина для в моем случае. Мы разрешаем его через pOpenInstansec [index] = None - для устранения всех дескрипторов, связанных с созданным процессом (например, stdin \ etc.) – N0dGrand87

Смежные вопросы