Почему я не могу импортировать из псевдонима модуля?

Я просто наткнулся на это неожиданное поведение в 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', который он не может найти. Вот почему псевдоним не будет работать.