简体   繁体   English

为什么我不能从模块别名导入?

[英]Why can't I import from a module alias?

I just stumbled across this unexpected behavior in python (both 2.7 and 3.x):我刚刚在 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'

Of course from re import search succeeds, just as it would have before I created the alias.当然from re import search成功了,就像在我创建别名之前一样。 But why can't I use the alias regexp , which is now a known module, as a source for importing names?但是为什么我不能使用别名regexp (现在是一个已知模块)作为导入名称的来源?

This sets you up for a nasty surprise whenever there are multiple variants of a module: Say I am still using Python 2 and I want to use the C version of pickle , cPickle .每当一个模块有多个变体时,这都会给您带来令人讨厌的惊喜:假设我仍在使用 Python 2 并且我想使用pickle的 C 版本cPickle If I then try to import a name from pickle , it will be fetched from the simple pickle module (and I won't notice since it doesn't throw an error!)如果我然后尝试从pickle导入一个名称,它将从简单的pickle模块中获取(我不会注意到,因为它不会抛出错误!)

>>> import cPickle as pickle
>>> from pickle import dump
>>> import inspect
>>> inspect.getsourcefile(dump)
'.../python2.7/pickle.py'    # Expected cPickle.dump 

Oops!哎呀!

Poking around I see that sys.modules includes the real module name ( re or cPickle , but not the alias regexp or pickle . That explains how the second import fails, but not why python module name resolution works this way, ie what the rules and rationale are for doing it this way.四处看看,我看到sys.modules包含真正的模块名称( recPickle ,但不是别名regexppickle 。这解释了第二次导入如何失败,但不是为什么python 模块名称解析以这种方式工作,即规则和这样做的理由是。

Note: This was marked as a duplicate of a question that has nothing to do with module aliasing: aliasing is not even mentioned in the question (which is about importing submodules from a package) or the top answers.注意:这被标记为与模块别名无关的问题的重复:在问题(这是关于从包中导入子模块)或最佳答案中甚至没有提到别名。 While the answers to that question provide information relevant to this question, the questions themselves are not even similar IMHO.虽然该问题的答案提供了与该问题相关的信息,但恕我直言,这些问题本身甚至都不相似。

In short:简而言之:

You can think of the loading process in that way:你可以这样想加载过程:

You can load a module into your program, in the form of a variable.您可以将模块以变​​量的形式加载到您的程序中。 You can name the variable for using the module whatever you want.您可以随意命名用于使用模块的变量 But, the loading process , is based on the name of the module's file, not "module variables".但是,加载过程基于模块文件的名称,而不是“模块变量”。


Long version:长版:

import re creates a global variable named re that serves as the "module portal", in the way it provides the ability to use the module operations. import re创建一个名为re的全局变量,用作“模块门户”,以提供使用模块操作的能力。

Most alike, import re as regex creates such a "portal" under the variable named regex .最相似的是, import re as regex在名为regex的变量下创建了这样一个“门户”。

But, when looking to create such portal and load the module functionality into it, the importer does not use such references.但是,在创建此类门户并将模块功能加载到其中时,导入程序使用此类引用。 Instead, it looks for the module in your python \\Lib directory, or your current working directory, as a file named re.py (or whatever is the name of the module you import).相反,它会在你的Python模块\\Lib目录或当前工作目录,文件名为re.py (或者是导入模块的名称)。

The import instructions does not address variables , but files , like #include<stdio.h> in C. They have their "own syntax", and set of instructions, as ruled by the interpreter structure, which is, to that case, the interpretation of re as a file name rather than a variable and as for ruling the name of the module "portal". import指令不针对变量,而是针对文件,例如 C 中的#include<stdio.h> 。它们有自己的“语法”和指令集,由解释器结构决定,在这种情况下,的解释re为文件名,而不是一个变量, as对执政模块“门户”之称。

That is why regex is an operation alias for the portal for re , but not an importation alias for the module (for that purpose you'll have to use the name of the file ).这就是为什么regexre门户的操作别名,而不是模块的导入别名(为此,您必须使用文件名)。

  • I have used terms like "module portal" and "operation alias" since I have not found any standard terms for these.我使用了诸如“模块门户”和“操作别名”之类的术语,因为我没有找到任何标准术语。 Most of the modules and importer mechanics is related to the interpreter implementation.大多数模块和导入器机制都与解释器实现有关。 In CPython (where the usage of the C API is common among developers), for example, create_module creates modules for the importer (in the form of PyObject s) using the provided specifications for the module, and the PyModule_NewObject and PyModule_New functions for the module instance creation that bears the module attributes.在CPython的(其中C API的使用是常见的开发者),例如, create_module对于进口商(的形式创建模块PyObject多个)使用所提供的规格为模块,并且PyModule_NewObjectPyModule_New对于模块功能具有模块属性的实例创建。 These can be viewed in the C API modules decumentation .这些可以在C API 模块 decumentation 中查看。

  • When I mentioned the term "portal" as a way to reference the variable created by the import statement, I meant to refer to it as a static portal, not a dynamic one.当我提到术语“门户”作为引用import语句创建的变量的一种方式时,我的意思是将其称为静态门户,而不是动态门户。 A change in the module file will not reflect in a running program that already imported it (as long as it didn't reload it), as it will load a copy of the module and use it, rather than asking the module file for the operations when encountering need.模块文件中的更改不会反映在已经导入它的正在运行的程序中(只要它没有重新加载它),因为它将加载模块的副本并使用它,而不是向模块文件询问遇到需要时的操作。


Here is pretty much how the variable loading goes realtime:以下是变量加载的实时方式:

>>> 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'>

You can see that re is the module referenced , and it was loaded from the file C:\\Programs\\Python35\\lib\\re.py (may change depending on where your python is installed).你可以看到re是被引用的模块,它是文件C:\\Programs\\Python35\\lib\\re.py (可能会根据你的 python 安装位置而改变)。

You cannot treat the module name in import statements as variables.您不能将 import 语句中的模块名称视为变量。 If that was the case, surely your initial import would fail because re is not yet a declared variable.如果是这种情况,您的初始导入肯定会失败,因为re还不是已声明的变量。 Basically the import statement is semantic sugar;基本上,import 语句是语义糖; it is a statement of its own with its own rules.它是自己的声明,有自己的规则。

One such rule is this: The written module name is understood as if it was a string.一个这样的规则是:写入的模块名称被理解为一个字符串。 That is, it does not lookup a variable with the name re , instead it uses the string value 're' directly as the sought after module name.也就是说,它不查找名称为re的变量,而是直接使用字符串值're'作为寻求的模块名称。 It then searches for a module/package (file) with this name and does the import.然后它搜索具有此名称的模块/包(文件)并进行导入。

This is the only situation ( Edit: Well, see the discussion in the comments...) in the language where this behavior is seen, which is the cause of the confusion.这是在语言中看到这种行为的唯一情况(编辑:嗯,请参阅评论中的讨论...),这是造成混淆的原因。 Consider this alternative syntax, which is much more in line with the rest of the Python language:考虑这种替代语法,它更符合 Python 语言的其余部分:

import 're'
# Or alternatively
module_name = 're'
import module_name

Here, variable expansion is assumed in the import statement.此处,在 import 语句中假定变量扩展。 As we know this is not the syntax which was actually chosen for the import statement.正如我们所知,这不是为 import 语句实际选择的语法。 One can discuss which syntax is the better one, but the above is definitely more harmonious with the rest of the language syntax.可以讨论哪种语法更好,但以上肯定与其他语言语法更和谐。

To get a definite answer on this you'll have to ask the designers themselves but, I think you're asking the wrong question.要获得明确的答案,您必须询问设计师自己,但是,我认为您问错了问题。

The question shouldn't be: Why is it done this way?" but, it should be, what would be the benefit of doing it the way you're asking? Surely it can be done but why should it?问题不应该是:为什么要这样做?”但是,应该是,按照您的要求这样做有什么好处?当然可以做到,但为什么要这样做?

As is the import statement is dead simple and very intuitive, you give it a file name, it tries to finds load it up.由于import语句非常简单且非常直观,您给它一个文件名,它会尝试查找加载它。 You even get fancy as and from but, the concept is simply, you write filenames and you let it be.你甚至可以幻想asfrom但是,这个概念是简单的,你写的文件名,你顺其自然。

What would obfuscating it and making it harder understand achieve, the only achievement is making things arguably more complex.什么会混淆它并使它更难理解实现,唯一的成就是使事情可以说更复杂。

Python has a history of looking for the rationale behind changes to its design, people asking why aren't function objects subclassable will get a "Why should they?" Python 有寻找其设计变化背后的基本原理的历史,人们在问为什么function对象不能被子类化时会得到一个“为什么他们应该?” reply;回复; this behavior doesn't really have a use-case.这种行为并没有真正的用例。 As is, the import is simple, intuitive and reminiscent of including/using files in other languages.照原样, import简单、直观,让人联想到包含/使用其他语言的文件。

When from import is used python tries to look in the from file to import what you have requested.当使用 from import 时,python 尝试查看 from 文件以导入您所请求的内容。 This might make it clearer.这可能会更清楚。

import re as regexp

from regexp import search 

This essentially asks python to look in a file called 'regexp' which it can't find.这实质上是要求 python 查看它无法找到的名为“regexp”的文件。 This is why the alias won't work.这就是别名不起作用的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM