412 votes

Comment puis-je obtenir une liste de toutes les classes du module actuel en Python ?

J'ai vu beaucoup d'exemples de personnes qui extraient toutes les classes d'un module, généralement quelque chose comme :

# foo.py
class Foo:
    pass

# test.py
import inspect
import foo

for name, obj in inspect.getmembers(foo):
    if inspect.isclass(obj):
        print obj

Génial.

Mais je n'arrive pas à trouver comment récupérer toutes les classes de la base de données. actuel module.

# foo.py
import inspect

class Foo:
    pass

def print_classes():
    for name, obj in inspect.getmembers(???): # what do I do here?
        if inspect.isclass(obj):
            print obj

# test.py
import foo

foo.print_classes()

C'est probablement quelque chose de très évident, mais je n'ai rien trouvé. Quelqu'un peut-il m'aider ?

2 votes

Il y avait un PEP pour une fonctionnalité comme celle-ci, mais elle a été rejetée.

0 votes

Qu'y a-t-il de mal à lire la source pour "class" ? Pourquoi cela ne fonctionne-t-il pas ?

81 votes

Je suppose que la question porte sur la volonté d'automatiser une tâche, et qu'il est donc important qu'elle soit effectuée de manière programmatique. On peut supposer que l'auteur de la question pense que le faire manuellement, en lisant le code source avec les yeux, pourrait être répétitif, source d'erreurs ou long.

519voto

Nadia Alramli Points 40381

Essayez ça :

import sys
current_module = sys.modules[__name__]

Dans votre contexte :

import sys, inspect
def print_classes():
    for name, obj in inspect.getmembers(sys.modules[__name__]):
        if inspect.isclass(obj):
            print(obj)

Et encore mieux :

clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass)

Parce que inspect.getmembers() prend un prédicat.

12 votes

Si j'importe les classes de ce module au niveau du module (c'est-à-dire, from optparse import OptionParser ) ces modules sont inclus dans la liste d'impression. Comment puis-je éviter cela ?

7 votes

@phasetwenty, au lieu de inspect.isclass vous pouvez avoir quelque chose comme : inspect.getmembers(sys.modules[__name__], lambda member: member.__module__ == __name__ and isnpect.isclass)

1 votes

Mais dict(inspect.getmembers(sys.modules[__name__])) == globals() est toujours True alors pourquoi les importations ?

24voto

int3 Points 6370

Je ne sais pas s'il y a une façon "correcte" de le faire, mais votre extrait est sur la bonne voie : ajoutez simplement import foo dans foo.py, faites inspect.getmembers(foo) et cela devrait fonctionner correctement.

0 votes

Whoa, j'aurais pensé que cela créerait une dépendance circulaire ou quelque chose comme ça, mais ça marche !

3 votes

La raison pour laquelle il n'y a pas de dépendance circulaire ou de boucle d'importation est qu'une fois que vous importez un module, il est ajouté à l'espace de noms global. Lorsque le module importé est exécuté et qu'il arrive à "import foo", il ignore l'importation car le module est déjà disponible dans les globaux. Si vous exécutez foo en tant que main (en tant que script), le module est en fait exécuté deux fois parce que lorsque vous arrivez à 'import foo' principal sera dans l'espace de noms global mais pas foo. Après 'import foo', les deux ' principal et 'foo' seront dans l'espace de noms des globaux.

23voto

Krab Points 1359

Qu'en est-il

g = globals().copy()
for name, obj in g.iteritems():

?

0 votes

C'est ce que je fais habituellement. Les autres réponses semblent beaucoup plus "propres", mais je ne les connaissais pas.

1 votes

Ça me semble assez propre, surtout si vous filtrez sur isinstance(obj, types.ClassType)

6 votes

Je préfère cette réponse car elle fonctionnera même si le module actuel n'a pas été placé dans sys.modules, par exemple à partir de docs.python.org/2/library/functions.html#execfile

12voto

ncoghlan Points 10779
import pyclbr
print(pyclbr.readmodule(__name__).keys())

Notez que le module de navigation des classes Python de la stdlib utilise l'analyse statique des sources, et ne fonctionne donc que pour les modules qui sont soutenus par un réel .py fichier.

2voto

Gary van der Merwe Points 2913

Il y avait un [PEP] pour une fonctionnalité de ce type, mais il a été rejeté.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X