Похоже, что вы неправильно установили файлы заголовков и статические библиотеки для 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
Давайте посмотрим, что делает этот оператор 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]). В противном случае каждое назначение внутри модуля, который не начинается с подчеркивания, будет добавлено к текущей локальной области.
В настоящее время я использую следующую функцию для получения списка имен и вызова 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('_')]
Это, наверное, самая хакерская вещь, которую ты видишь за весь день, но это может сработать.
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 ) )