11
votes

Solution OsError avec Os.listdir

J'ai un répertoire avec des fichiers de 90 km. Ceci est un nombre tellement énorme de fichiers qui bash fonctionne comme ls échoue. Donc bien sûr, os.listdir () de mon script Python (Mac Python, version 2.5); Il échoue avec Oserror: [errno 12] Impossible d'allouer la mémoire: '.'

Les gens diront "Ne mettez pas ce plusieurs fichiers dans un seul répertoire! Êtes-vous fou?" - mais j'aime prétendre que je vis dans le futur, un endroit brillant et brillant, où j'ai des gigaoctets de mémoire à ma disposition et que je n'ai pas besoin de m'inquiéter trop sur où se passe exactement mes fichiers, aussi longtemps qu'il y ait Rust à gauche sur mes plateaux de rotation.

Alors, y a-t-il une bonne solution de contournement pour ce os.listdir () problème? J'ai envisagé juste de bombarder à trouver , mais c'est un peu brut, et malheureusement Recherche est récursif, sans option maxdePTH prise en charge sur Mac OS X 10.6.

Voici ce que l'Os.Listdir via des bombardements à découvrir ressemble à des ressemblons, grossièrement: xxx

mise à jour: os.listdir () réussit à Python 2.6.


11 commentaires

Quelle est l'erreur que vous obtenez? J'utilise régulièrement os.listdir pour obtenir des listes de répertoires avec des fichiers 50-100k en eux. OS.LISTDIR est également le choix le plus rapide, car il ne stat chaque fichier dans le répertoire.


@Seth, je reçois Oserror: [errno 12] ne peut pas allouer la mémoire: '.' '


Environ combien de fichiers sont dans ce répertoire?


@Garrett reçoit un A + pour la compréhension de lecture. RÉ:


Eh bien, pensez-y. "J'ai un répertoire avec des fichiers de 90 km," est ambigu. Cela pourrait signifier: "Le contenu de l'annuaire totale 90k," ou "le répertoire dispose de N nombre de fichiers 90k." Donc, je suis curieux de savoir si les problèmes réside avec la taille totale du fichier ou le nombre total de fichiers.


Je ne pense pas que quatre fichiers 90k seraient admissibles comme un "nombre énorme de fichiers" absurvement énorme ". : P


Quel Python (Ports Mac, Apple, quelle version?), Quel Mac OS X? Vous devez frapper un bug dans une ancienne version Python. Je viens de répertorie un répertoire avec 65000 fichiers dedans et Python utilise uniquement 8 Mo de VR + 23MB VM.


@Garett 90 000 fichiers de différentes tailles.


@Seth J'utilise Python d'Apple 2.5.4 sur OS X 10.6.


+1 pour le mettre éloquemment :) Les gens diront "Ne mettez pas ce plusieurs fichiers dans un seul répertoire! Êtes-vous fou?" - mais j'aime prétendre que je vis dans le futur, un endroit brillant et brillant, où j'ai des gigaoctets de mémoire à ma disposition et que je n'ai pas besoin de m'inquiéter trop sur où se passe exactement mes fichiers, aussi longtemps qu'il y ait rouille laissée sur mes plateaux de filature.


Ironiquement, ici en 2013, la plupart des ordinateurs portables Mac ont des SSD afin qu'ils ne soient donc pas à craindre de filer les plateaux, beaucoup moins de rouille.


4 Réponses :


2
votes
def ls(directory): 
    """full-featured solution, via wrapping find"""
    import os
    files = os.popen4('find %s' % directory)[1].read().rstrip().split('\n')
    files.remove(directory)
    n = len(directory)
    if directory[-1] != os.path.sep:
        n += 1
    files = [f[n:] for f in files] # remove dir prefix
    return [f for f in files if os.path.sep not in f] # remove files in sub-directories

2 commentaires

Oui, cela fonctionnerait, mais ne vous aidera pas avec le problème de performance sur les fichiers 90K.


Je cherche juste quelque chose qui fonctionnerait - ne vous souciez pas de la performance. Une solution performante qui ne fonctionne pas n'est pas une solution.



4
votes

Vous pouvez essayer d'aller un niveau plus profond et d'appeler directement Opendir () et ReadDir () à l'aide de CTYPES.


2 commentaires

Désespéré, mais si listdir et ls échoue c'est la seule chose que je puisse penser.


Ceci est tentant, mais le problème est que lavedir renvoie les données sous forme de struct direct et la disposition de celle-ci est spécifique à la plate-forme. Je pense que le seul moyen de mettre en œuvre fiable est avec un module natif.



7
votes

Vous frappez un artefact historique en Python: os.listdir doit renvoyer un itérateur, pas un tableau. Je pense que cette fonction prédit les itérateurs - il est étrange qu'aucun os.xlistdir a été ajouté.

Cela a plus d'effets que l'utilisation de la mémoire sur d'énormes répertoires. Même sur un répertoire avec seulement quelques milliers de fichiers, vous devez attendre que l'ensemble du répertoire soit terminé, et vous devez lire le répertoire entier , même si la première entrée est la celui que vous recherchiez.

Ceci est un manque étroitement criant en Python: il semble y avoir no la liaison au niveau de bas niveau Opendir / lisdedir / Fdopendir API, il semble donc que ce ne soit même pas possible de la mettre en œuvre sans écrire un module natif. C'est l'un de ces cas où il s'agit d'un trou si énorme et béant dans la bibliothèque standard que je doute de moi et soupçonnez que je ne le vois pas - il y a de bas niveau ouvert , Stat , etc. Les liaisons, et ceci est dans la même catégorie.


8 commentaires

Toujours agréable de voir des bowvotes mystérieux. Je suppose que c'est le "osant critiquer la pénalité de Python".


ImporterRor: Aucun module nommé critiquait


Cela impliquerait importerror: aucun module nommé amélioration .


Ou vous êtes évité de ne pas répondre à "Y a-t-il une bonne solution de contournement?" question.


@Russell: Ma réponse à celle-ci était assez simple: comme il n'y a pas de Opendir Binding, écrit un module natif, il n'y a pas de solution de contournement pour ce problème. (Bien sûr, je suis conscient que beaucoup de gens vont baisser les choses sans déranger de les lire.)


J'ai traité avec un xlistdir () un moment de retour et cela a fonctionné pour mes fins limitées. Aujourd'hui, j'irais avec une solution CTTYPES. +1 pour l'ajouter au python standard.


@Terrel, CTTYPES serait spécifique à la plate-forme, en fonction de la disposition exacte de Dirent . Je recommanderais fortement contre cela.


UGG..Vous cela n'existe vraiment pas dans la bibliothèque standard Python?



2
votes

Je reçois le même Ioerror sur Apple Python 2.5.5 sur 10.6 lors de la liste d'un grand répertoire. Cela fonctionne juste bien dans Python2.6.

Python 2.5.5 (r255:77872, Sep 21 2010, 09:52:31) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> x = os.listdir('.')
OSError: [Errno 12] Cannot allocate memory: '.'


0 commentaires