Все члены пакета / модуля определяет?

1

Как узнать, какие члены модуля/пакета определяют? Определив, я имею в виду:

somemodule.py

import os # <-- Not defined in this module
from os.path import sep # <-- Not defined in this module

I_AM_ATTRIBUTE = None # <-- Is defined in this module

class SomeClass(object): # <-- Is defined also...
    pass

Поэтому мне нужна какая-то функция, которая при вызове будет давать только I_AM_ATTRIBUTE и SomeClass.

Теперь я пытаюсь использовать dir(somemodule), но как узнать, какие из них определены в somemodule? Проверка на __module__ не работает, поскольку это не определено в модулях и атрибутах (например, os package или sep).

Очевидно, что дикий импорт (from somemodule import *) также не позволяет их фильтровать, так что даже возможно?

Лучшее, что я могу получить, это:

import somemodule

for name in dir(somemodule):
    try:
        value = getattr(somemodule, name)
    except:
        pass
    else:
        if hasattr(value, "__module__"):
            if value.__module__ != somemodule.__name__:
                continue
        if hasattr(value, "__name__"):
            if not value.__name__.startswith(__name__):
                continue
        print "somemodule defines:", name

Выбирает os, но оставляет sep.

  • 1
    Что не так с чтением источника? Вы можете легко понять это, прочитав? Почему бы просто не прочитать?
Теги:

2 ответа

1
Лучший ответ

Что означает "определить"? Для меня определено, что некоторый символ является частью открытого интерфейса модуля. Это совпадает с тем, как кажется, что вы пытаетесь использовать этот термин, в том числе и в вашем примере, но если у вас есть какая-то цель, которая не согласуется с этим определением, вам придется прояснить вопрос о том, что вы действительно пытаясь сделать. Это делает проблему с документацией.

Таким образом, вы не можете знать, что определяет модуль, а некоторые вещи, которые импортируются, могут по-прежнему быть "определены в этом модуле" или "определены как часть общедоступного интерфейса этого модуля". Это часто происходит при импорте из частного модуля, включая модули расширения C.

Для ваших собственных модулей используйте __all__ (можете сделать это легко) или неофициальный префикс подчеркивания для непубличных (например, _private_var = 42). Оба соглашения распознаются с помощью help() и должны использоваться другими генераторами документации.

  • 0
    Хех, держу пари, что вы читали мой предыдущий вопрос ... Так как я пытаюсь создать генератор документации (фактически улучшая Sphinx) для автоматического документирования пакетов, и размышляю над тем фактом, что если модуль не имеет __all__ , какие вещи должны мы документируем? Я, вероятно, заканчиваю использовать вышеуказанный код, если __all__ не определен ... По крайней мере, он удаляет "os" и такой импорт отключается.
  • 0
    Нет, на самом деле я не читал это, но я попытался сделать то, что вы действительно хотели сделать, вместо того, чтобы попытаться исправить ваше попытанное решение. :)
Показать ещё 2 комментария
1

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

Что касается дикого импорта, запуск from somemodule import * в вашем примере будет импортировать все атрибуты, включая os и sep. Если пакет содержит переменную __all__, дикий импорт импортирует имена, содержащиеся в нем. В противном случае он будет импортировать все имена, не начинающиеся с подчеркивания, независимо от того, из какого модуля они изначально.

  • 0
    Я отредактировал вопрос, я также обнаружил, что от «os» можно __name__ если проверено с помощью __name__ .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню