2010-12-08 19 views
21

Escribí un tipo de paquete de prueba que requiere mucho uso de archivos. Después de un tiempo (2h) obtengo un IOError: [Errno 24] Too many open files: '/tmp/tmpxsqYPm'. Comprobé dos veces todos los identificadores de archivo si los cierro nuevamente. Pero el error todavía existe.Demasiados archivos abiertos en python

Me trataron de averiguar el número de descriptores de archivos permitidos utilizando resource.RLIMIT_NOFILE y el número de desciptors archivo abiertos actualmente:

def get_open_fds(): 

    fds = [] 
    for fd in range(3,resource.RLIMIT_NOFILE): 
      try: 
        flags = fcntl.fcntl(fd, fcntl.F_GETFD) 
      except IOError: 
        continue 

      fds.append(fd) 

    return fds 

Así que si funciono con la siguiente prueba:

print get_open_fds() 
for i in range(0,100): 
    f = open("/tmp/test_%i" % i, "w") 
    f.write("test") 
    print get_open_fds() 

consigo esta salida:

[] 
/tmp/test_0 
[3] 
/tmp/test_1 
[4] 
/tmp/test_2 
[3] 
/tmp/test_3 
[4] 
/tmp/test_4 
[3] 
/tmp/test_5 
[4] ... 

Eso es extraño, esperaba una n aumento en el número de descriptores de archivos abiertos. ¿Mi guión es correcto?

Estoy usando el registrador y el subproceso de Python. ¿Podría ser esa la razón de mi fuga de fd?

Gracias, Daniel

+0

favor cat/proc/sys/fs/file-max y cat/proc/sys/fs/file-nr –

+2

debe utilizar 'resource.getrlimit (resource.RLIMIT_NOFILE) '. 'resource.RLIMIT_NOFILE' es solo una constante para acceder a la información. – chuck

+0

Subprocess.Popen causa problemas similares? – Joe

Respuesta

11

Su escritura de la prueba sobrescribe f cada iteración, lo que significa que el archivo se cierran cada vez. Tanto el registro en archivos como subprocess con tuberías agota las descripciones, lo que puede llevar al agotamiento.

+0

mi culpa, ¡gracias por la pista! Parece que get_open_fds() hace su trabajo. Pero resource.RLIMIT_NOFILE = 7 y mi el error ocurre después de que abrí 1024 archivos. De todos modos, sé cómo depurar mis scripts, ¡gracias hasta ahora! – dmorlock

+1

@Informant ¿puedes publicar la corrección también? Tengo el mismo problema pero no sé cómo solucionarlo. Gracias. – AliBZ

8

resource.RLIMIT_NOFILE es efectivamente el 7, pero eso es un índice en resource.getrlimit(), no es el límite en sí ... resource.getrlimit (resource.RLIMIT_NOFILE) es lo que usted quiere que su rango superior() para ser

11

El código corregido es:

import resource 
import fcntl 
import os 

def get_open_fds(): 
    fds = [] 
    soft, hard = resource.getrlimit(resource.RLIMIT_NOFILE) 
    for fd in range(0, soft): 
     try: 
      flags = fcntl.fcntl(fd, fcntl.F_GETFD) 
     except IOError: 
      continue 
     fds.append(fd) 
    return fds 

def get_file_names_from_file_number(fds): 
    names = [] 
    for fd in fds: 
     names.append(os.readlink('/proc/self/fd/%d' % fd)) 
    return names 

fds = get_open_fds() 
print get_file_names_from_file_number(fds) 
Cuestiones relacionadas