Почему я не могу импортировать из псевдонима модуля?
Я просто наткнулся на это неожиданное поведение в python (оба 2.7 и 3.x):
>>> import re as regexp
>>> regexp
<module 're' from '.../re.py'>
>>> from regexp import search
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'regexp'
Конечно, from re import search
преуспевает, как и раньше, чем я создал псевдоним. Но почему я не могу использовать псевдоним regexp
, который теперь является известным модулем, в качестве источника для импорта имен?
Это дает вам неприятный сюрприз, когда есть несколько вариантов модуля: Скажем, я все еще использую Python 2, и я хочу использовать версию C pickle
, cPickle
. Если я попытаюсь импортировать имя из pickle
, он будет извлечен из простого модуля pickle
(и я не заметлю, так как он не выдает ошибку!)
>>> import cPickle as pickle
>>> from pickle import dump
>>> import inspect
>>> inspect.getsourcefile(dump)
'.../python2.7/pickle.py' # Expected cPickle.dump
К сожалению,
Я вижу, что sys.modules
содержит имя реального модуля (re
или cPickle
, но не псевдоним regexp
или pickle
). Это объясняет, как второй импорт выходит из строя, но не почему модуль python разрешение имен работает таким образом, то есть, какие правила и обоснования предназначены для этого.
Примечание. Это было отмечено как дубликат вопроса, который не имеет ничего общего с псевдонимом модуля: aliasing даже не упоминается в вопрос (который касается импорта подмодулей из пакета) или верхние ответы. Хотя ответы на этот вопрос предоставляют информацию, относящуюся к этому вопросу, сами вопросы не похожи даже на ИМХО.
Ответы
Ответ 1
Короче:
Вы можете думать о процессе загрузки таким образом:
Вы можете загрузить модуль в свою программу в виде переменной. Вы можете назовите переменную для использования модуля, что хотите. Но процесс загрузки основан на имени файла модуля, а не на "переменных модуля".
Длинная версия:
import re
создает глобальную переменную с именем re
, которая служит как "портал модуля", так как она обеспечивает возможность использования операций модуля.
В наибольшей степени import re as regex
создает такой "портал" под переменной с именем regex
.
Но, глядя на создание такого портала и загрузку функциональности модуля в него, импортер не использует такие ссылки. Вместо этого он ищет модуль в вашем каталоге python \Lib
или в вашем текущем рабочем каталоге как файл с именем re.py
(или что-то другое - имя импортируемого модуля).
В инструкциях import
не рассматриваются переменные, а файлы, такие как #include<stdio.h>
в C. Они имеют свой "собственный синтаксис" и набор инструкций, управляемых структурой интерпретатора, которая, в этом случае, интерпретация re
как имени файла, а не переменной и as
для определения имени модуля "портал" .
Вот почему regex
- это псевдоним операции для портала для re
, но не псевдоним импорта для модуля (для этого вам нужно будет использовать имя файл).
-
Я использовал такие термины, как "модуль-портал" и "псевдоним работы", так как я не нашел для них стандартных терминов. Большинство модулей и механики импортера связаны с внедрением интерпретатора. В CPython (где использование C API является общим для разработчиков), например, create_module
создает модули для импортера (в форма PyObject
s), используя предоставленные спецификации для модуля, и PyModule_NewObject
и PyModule_New
функции для создания экземпляра модуля, который несет атрибуты модуля. Они могут быть просмотрены в C API-модулях.
-
Когда я упомянул термин "портал" как способ ссылки на переменную, созданную оператором import
, я имел в виду ссылку на нее как статический портал, а не динамический. Изменение файла модуля не будет отражено в запущенной программе, которая уже импортировала ее (если она не перезагрузила ее), так как она загрузит копию модуля и использует его, вместо того, чтобы запрашивать файл модуля для операций при возникновении необходимости.
Вот в основном то, как переменная загрузка идет в реальном времени:
>>> import re
>>> re
<module 're' from 'C:\\Programs\\Python35\\lib\\re.py'>
>>> import re as regex
>>> regex
<module 're' from 'C:\\Programs\\Python35\\lib\\re.py'>
Вы можете видеть, что re
- это модуль , на который ссылается, и он был загружен из файла C:\Programs\Python35\lib\re.py
(может меняться в зависимости от того, где установлен ваш python).
Ответ 2
Вы не можете рассматривать имя модуля в операторах импорта как переменные. Если это так, то ваш исходный импорт будет неудачным, потому что re
еще не является объявленной переменной. В основном выражение импорта - семантический сахар; это собственное выражение со своими собственными правилами.
Одно из таких правил: имя написанного модуля понимается так, как если бы оно было строкой. То есть он не ищет переменную с именем re
, вместо этого она использует строковое значение 're'
непосредственно как имя запрашиваемого модуля. Затем он ищет модуль/пакет (файл) с этим именем и выполняет импорт.
Это единственная ситуация ( Изменить: Хорошо, см. обсуждение в комментариях...) на языке, где это поведение видно, что является причиной путаницы. Рассмотрим этот альтернативный синтаксис, который намного больше соответствует остальному языку Python:
import 're'
# Or alternatively
module_name = 're'
import module_name
Здесь переменное расширение предполагается в инструкции import. Как мы знаем, это не синтаксис, который был фактически выбран для оператора импорта. Можно обсуждать, какой синтаксис лучше, но выше определенно более гармонично с остальным синтаксисом языка.
Ответ 3
Чтобы получить определенный ответ на это, вам придется спросить самих дизайнеров, но, думаю, вы задаете неправильный вопрос.
Вопрос не должен быть: почему это делается так? ", но, должно быть, было бы полезно сделать это так, как вы просите? Конечно, это можно сделать, но почему это должно быть?
Как и оператор import
мертв, прост и очень интуитивен, вы даете ему имя файла, он пытается найти его. Вы даже получаете фантазии as
и from
, но концепция проста: вы пишете имена файлов, и вы позволяете им быть.
Что бы запутать его и усложнить его достижение, единственное достижение - это сделать вещи более сложными.
У Python есть история поиска обоснований изменений в его дизайне, люди спрашивают, почему нет function
объектов subclassable, получит "Почему они должны?" Ответить; это поведение на самом деле не имеет прецедента. Как и в случае, import
прост, интуитивно понятен и напоминает включение/использование файлов на других языках.
Ответ 4
Когда используется импорт, python пытается посмотреть в файле из файла, чтобы импортировать запрошенные вами данные. Это может сделать его более ясным.
import re as regexp
from regexp import search
Это, по сути, требует, чтобы python просматривал файл с именем 'regexp', который он не может найти. Вот почему псевдоним не будет работать.