Как определить, что импортируется через `from m import *`?

Похоже, что вы неправильно установили файлы заголовков и статические библиотеки для python dev. Используйте диспетчер пакетов, чтобы установить их в системном масштабе.

Для apt (Ubuntu, Debian ...):

sudo apt-get install python-dev   # for python2.x installs
sudo apt-get install python3-dev  # for python3.x installs

Для yum (CentOS, RHEL ...):

sudo yum install python-devel   # for python2.x installs
sudo yum install python34-devel   # for python3.4 installs

Для dnf (Fedora ...):

sudo dnf install python2-devel  # for python2.x installs
sudo dnf install python3-devel  # for python3.x installs

Для zypper (openSUSE ...):

sudo zypper in python-devel   # for python2.x installs
sudo zypper in python3-devel  # for python3.x installs

Для apk ( Alpine ...):

# This is a departure from the normal Alpine naming
# scheme, which uses py2- and py3- prefixes
sudo apk add python2-dev  # for python2.x installs
sudo apk add python3-dev  # for python3.x installs
2
задан Thom Smith 21 February 2019 в 03:14
поделиться

3 ответа

Давайте посмотрим, что делает этот оператор from m import *:

>>> dis.dis(compile('from m import *', '<module>', 'single'))
  1           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (('*',))
              4 IMPORT_NAME              0 (m)
              6 IMPORT_STAR
              8 LOAD_CONST               2 (None)
             10 RETURN_VALUE

Ключевым моментом здесь является то, что он фактически вызывает выделенный код операции IMPORT_STAR, и это реализация, специфичная для интерпретатора, который будет выполнить этот код Этот оператор был первоначально указан в PEP-0221 , но подробности реализации указаны в комментариях, представленных в этом конкретном коммите .

В CPython это найдено в /Python/ceval.c (Python 3.7.2), и оно по очереди вызывает import_all_from , которое показывает общую логику того, что это на самом деле делает внутри интерпретатор байт-кода.

В PyPy это найдено в /pypy/interpreter/pyopcode.py , и опять же, как и в реализации C, оно вызывает функцию import_all_from , определенную в RPython, которая также имеет похожую логику но в более привычном синтаксисе для программистов на Python.

Как в реализации CPython, так и в pypy, если __all__ представлен в виде списка имен в импортированном модуле, все соответствующие назначения будут добавлены в текущую локальную область, включая те имена, которые имеют префикс с подчеркиванием ([ 118]). В противном случае каждое назначение внутри модуля, который не начинается с подчеркивания, будет добавлено к текущей локальной области.

0
ответ дан metatoaster 21 February 2019 в 03:14
поделиться

В настоящее время я использую следующую функцию для получения списка имен и вызова getattr(m, name) для каждого имени:

def public_members(module):
    try:
        return module.__all__  # If not iterable, imports will break.
    except AttributeError:
        return [name for name in dir(module) if not name.startswith('_')]
0
ответ дан Thom Smith 21 February 2019 в 03:14
поделиться

Это, наверное, самая хакерская вещь, которую ты видишь за весь день, но это может сработать.

bound = globals().copy()
from module import *
for k, v in list( globals().items() ):
    if k not in bound or bound[ k ] != v:
        print( 'new', repr( k ), repr( v ) )
0
ответ дан Michael Speer 21 February 2019 в 03:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: