2010-12-08 25 views
21

J'ai écrit une sorte de suite de tests qui nécessite beaucoup de fichiers. Après un certain temps (2h) j'obtiens un IOError: [Errno 24] Too many open files: '/tmp/tmpxsqYPm'. J'ai vérifié toutes les poignées de fichier si je les referme. Mais l'erreur existe toujours.Trop de fichiers ouverts en python

J'ai essayé de calculer le nombre de descripteurs de fichiers autorisés en utilisant resource.RLIMIT_NOFILE et le nombre de desciptors de fichiers actuellement ouverts:

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 

Donc, si je lance le test suivant:

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

Je reçois cette sortie:

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

C'est étrange, je m'attendais à un n nombre croissant de descripteurs de fichiers ouverts. Est-ce que mon script est correct? J'utilise le logger et le sous-processus de python. Serait-ce la raison de ma fuite fd?

Merci, Daniel

+0

s'il vous plaît cat/proc/sys/fs/file-max et cat/proc/sys/fs/file-nr –

+2

Vous devez utiliser 'resource.getrlimit (resource.RLIMIT_NOFILE) '. 'resource.RLIMIT_NOFILE' est juste un constanct pour accéder à l'information. – chuck

+0

Est-ce que subprocess.Popen pourrait causer des problèmes similaires? – Joe

Répondre

11

Votre script de test f chaque itération remplace, ce qui signifie que le fichier va se fermer à chaque fois. La journalisation dans des fichiers et subprocess avec des tuyaux utilisent des descripteurs, ce qui peut conduire à l'épuisement.

+0

ma faute, merci pour l'indice! Il semble que get_open_fds() fasse son travail. Mais resource.RLIMIT_NOFILE = 7 et mon erreur se produit après avoir ouvert 1024 fichiers. De toute façon, je sais déboguer mes scripts - merci pour l'instant !!! – dmorlock

+1

@Informant pouvez-vous poster le correctif aussi? J'ai le même problème mais je ne sais pas comment le réparer. Merci. – AliBZ

8

resource.RLIMIT_NOFILE est en effet 7, mais qui est un index dans resource.getrlimit(), pas la limite elle-même ... resource.getrlimit (resource.RLIMIT_NOFILE) est ce que vous voulez que votre haut de gamme() pour être

11

Le code corrigé est:

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)