使用“导入模块”; 或者“从模块导入”?

发布于 2024-07-16 05:19:53 字数 180 浏览 7 评论 0原文

我试图找到关于最好使用 import module 还是 from module import 的综合指南。 我刚刚开始使用 Python,并尝试从最佳实践开始。

基本上,我希望是否有人可以分享他们的经验,其他开发人员有哪些偏好,以及避免未来遇到任何问题的最佳方法是什么?

I've tried to find a comprehensive guide on whether it is best to use import module or from module import. I've just started with Python and I'm trying to start off with best practices in mind.

Basically, I was hoping if anyone could share their experiences, what preferences other developers have and what's the best way to avoid any gotchas down the road?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(23

内心激荡 2024-07-23 05:19:54

这是我当前目录的目录结构:

<前><代码>。
└─a
└─b
└─c

  1. import 语句会记住所有中间名称
    这些名称必须合格:

    在[1]中:导入 abc 
    
      在[2]中: 
      Out[2]: <模块'a'(命名空间)> 
    
      在[3]中:ab 
      Out[3]: <模块 'ab' (命名空间)> 
    
      在[4]中:abc 
      Out[4]: <模块'abc'(命名空间)> 
      
  2. from ... import ... 语句仅记住导入的名称
    此名称不得被限定:

    在[1]中:from ab import c 
    
      在[2]中: 
      NameError:名称“a”未定义 
    
      在[2]中: ab 
      NameError:名称“a”未定义 
    
      在[3]中:abc 
      NameError:名称“a”未定义 
    
      在[4]中:c 
      Out[4]: <模块'abc'(命名空间)> 
      

  • 注意:当然,我在步骤 1 和 2 之间重新启动了我的 Python 控制台。

This is my directory structure of my current directory:

.  
└─a  
   └─b  
     └─c
  1. The import statement remembers all intermediate names.
    These names have to be qualified:

    In[1]: import a.b.c
    
    In[2]: a
    Out[2]: <module 'a' (namespace)>
    
    In[3]: a.b
    Out[3]: <module 'a.b' (namespace)>
    
    In[4]: a.b.c
    Out[4]: <module 'a.b.c' (namespace)>
    
  2. The from ... import ... statement remembers only the imported name.
    This name must not be qualified:

    In[1]: from a.b import c
    
    In[2]: a
    NameError: name 'a' is not defined
    
    In[2]: a.b
    NameError: name 'a' is not defined
    
    In[3]: a.b.c
    NameError: name 'a' is not defined
    
    In[4]: c
    Out[4]: <module 'a.b.c' (namespace)>
    

  • Note: Of course, I restarted my Python console between steps 1 and 2.
一个人的旅程 2024-07-23 05:19:54

补充一下人们对 from x import * 的看法:除了让辨别名称的来源变得更加困难之外,这还会导致像 Pylint 这样的代码检查器无法使用。 他们会将这些名称报告为未定义的变量。

To add to what people have said about from x import *: besides making it more difficult to tell where names came from, this throws off code checkers like Pylint. They will report those names as undefined variables.

§对你不离不弃 2024-07-23 05:19:54

我自己对此的回答主要取决于首先,我将使用多少个不同的模块。 如果我只打算使用一两个,我通常会使用 from ... import因为它可以减少文件其余部分中的击键次数,但如果我要使用许多不同的模块,我更喜欢 import 因为这意味着每个模块参考是自记录的。 我可以看到每个符号的来源,而无需四处寻找。

通常,我更喜欢普通导入的自记录风格,只有当我必须输入模块名称的次数超过 10 到 20 次时,才会更改为 from.. import,即使只导入一个模块。

My own answer to this depends mostly on first, how many different modules I'll be using. If i'm only going to use one or two, I'll often use from ... import since it makes for fewer keystrokes in the rest of the file, but if I'm going to make use of many different modules, I prefer just import because that means that each module reference is self-documenting. I can see where each symbol comes from without having to hunt around.

Usuaully I prefer the self documenting style of plain import and only change to from.. import when the number of times I have to type the module name grows above 10 to 20, even if there's only one module being imported.

夏雨凉 2024-07-23 05:19:54

有很多答案,但没有提到测试(使用 unittestpytest)。

tl;dr

对外部模块使用 import foo 来简化测试。

困难的方法

从模块中单独导入类/函数(from foo import bar)会使红绿重构循环变得乏味。 例如,如果我的文件看起来像

# my_module.py

from foo import bar


class Thing:
    def do_thing(self):
        bar('do a thing')

并且我的测试是

# test_my_module.py

from unittest.mock import patch
import my_module


patch.object(my_module, 'bar')
def test_do_thing(mock_bar):
    my_module.Thing().do_thing()
    mock_bar.assert_called_with('do a thing')

乍一看,这看起来很棒。 但是,如果我想在不同的文件中实现 Thing 类,会发生什么情况? 我的结构必须像这样改变......

# my_module.py

from tools import Thing


def do_thing():
    Thing().do_thing()


# tools.py

from foo import bar


class Thing:
    def do_thing(self):
        bar('do a thing')


# test_my_module.py

from unittest.mock import patch
import my_module
import tools  # Had to import implementation file...


patch.object(tools, 'bar')  # Changed patch
def test_do_thing(mock_bar):
    my_module.do_thing()  # Changed test (expected)
    mock_bar.assert_called_with('do a thing')

不幸的是,由于我使用了 from foo import bar ,我需要更新我的补丁以引用tools模块。 本质上,由于我的测试对实现了解太多,因此需要进行比预期更多的更改才能进行此重构。

更好的方法

使用import foo,我的测试可以忽略模块的实现方式并简单地修补整个模块。

# my_module.py

from tools import Thing


def do_thing():
    Thing().do_thing()


# tools.py

import foo


class Thing:
    def do_thing(self):
        foo.bar('do a thing')  # Specify 'bar' is from 'foo' module


# test_my_module.py

from unittest.mock import patch
import my_module


patch('foo')  # Patch entire foo module
def test_do_thing(mock_foo):
    my_module.do_thing()  # Changed test (expected)
    mock_foo.bar.assert_called_with('do a thing')

您的测试了解的实现细节越少越好。 这样,如果您想出更好的解决方案(使用类而不是函数,使用附加文件来分离想法等),则在测试中需要进行的更改就更少以适应重构。

There have been many answers, but none have mentioned testing (with unittest or pytest).

tl;dr

Use import foo for external modules to simplify testing.

The Hard Way

Importing classes/functions (from foo import bar) individually from a module makes red-green-refactor cycles tedious. For example, if my file looks like

# my_module.py

from foo import bar


class Thing:
    def do_thing(self):
        bar('do a thing')

and my test is

# test_my_module.py

from unittest.mock import patch
import my_module


patch.object(my_module, 'bar')
def test_do_thing(mock_bar):
    my_module.Thing().do_thing()
    mock_bar.assert_called_with('do a thing')

At first glance, this seems great. But what happens if I want to implement Thing class in a different file? My structure would have to change like this...

# my_module.py

from tools import Thing


def do_thing():
    Thing().do_thing()


# tools.py

from foo import bar


class Thing:
    def do_thing(self):
        bar('do a thing')


# test_my_module.py

from unittest.mock import patch
import my_module
import tools  # Had to import implementation file...


patch.object(tools, 'bar')  # Changed patch
def test_do_thing(mock_bar):
    my_module.do_thing()  # Changed test (expected)
    mock_bar.assert_called_with('do a thing')

Unfortunately, since I used from foo import bar, I need to update my patch to reference the tools module. Essentially, since my test knows too much about implementation, much more than expected needs to be changed to do this refactor.

The Better Approach

Using import foo, my tests can ignore how the module is implemented and simply patch the whole module.

# my_module.py

from tools import Thing


def do_thing():
    Thing().do_thing()


# tools.py

import foo


class Thing:
    def do_thing(self):
        foo.bar('do a thing')  # Specify 'bar' is from 'foo' module


# test_my_module.py

from unittest.mock import patch
import my_module


patch('foo')  # Patch entire foo module
def test_do_thing(mock_foo):
    my_module.do_thing()  # Changed test (expected)
    mock_foo.bar.assert_called_with('do a thing')

The less implementation details your tests know, the better. That way, if you come up with a better solution (use classes instead of functions, use additional files to separate ideas, etc.), less needs to be changed in your tests to accommodate the refactor.

百合的盛世恋 2024-07-23 05:19:54

我发现的一个显着差异令人惊讶没有人谈论过,那就是使用简单的导入你可以访问私有变量来自导入模块的私有函数,这是 from-import 语句不可能实现的。

输入图片此处描述

图片中的代码:

setting.py

public_variable = 42
_private_variable = 141
def public_function():
    print("I'm a public function! yay!")
def _private_function():
    print("Ain't nobody accessing me from another module...usually")

plain_importer.py

import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()

# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually

from_importer.py

from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function()   #doesn't work

One of the significant difference I found out which surprisingly no-one has talked about is that using plain import you can access private variable and private functions from the imported module, which isn't possible with from-import statement.

enter image description here

Code in image:

setting.py

public_variable = 42
_private_variable = 141
def public_function():
    print("I'm a public function! yay!")
def _private_function():
    print("Ain't nobody accessing me from another module...usually")

plain_importer.py

import settings
print (settings._private_variable)
print (settings.public_variable)
settings.public_function()
settings._private_function()

# Prints:
# 141
# 42
# I'm a public function! yay!
# Ain't nobody accessing me from another module...usually

from_importer.py

from settings import *
#print (_private_variable) #doesn't work
print (public_variable)
public_function()
#_private_function()   #doesn't work
挽你眉间 2024-07-23 05:19:54

正如 Jan Wrobel 提到的,不同导入的一个方面是导入的披露方式。

模块mymath

from math import gcd
...

mymath的使用:

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

如果我导入gcd只是为了内部使用,而不是透露给mymath的用户>,这可能会很不方便。 我经常遇到这种情况,在大多数情况下我想“保持我的模块干净”。

除了 Jan Wrobel 提出通过使用 import math 来模糊这一点的建议之外,我已经开始通过使用前导下划线来隐藏导入以防止公开:

# for instance...
from math import gcd as _gcd
# or...
import math as _math

在较大的项目中这种“最佳实践”使我能够准确控制向后续进口披露的内容以及不披露的内容。 这使我的模块保持干净,并在一定规模的项目中得到回报。

As Jan Wrobel mentions, one aspect of the different imports is in which way the imports are disclosed.

Module mymath

from math import gcd
...

Use of mymath:

import mymath
mymath.gcd(30, 42)  # will work though maybe not expected

If I imported gcd only for internal use, not to disclose it to users of mymath, this can be inconvenient. I have this pretty often, and in most cases I want to "keep my modules clean".

Apart from the proposal of Jan Wrobel to obscure this a bit more by using import math instead, I have started to hide imports from disclosure by using a leading underscore:

# for instance...
from math import gcd as _gcd
# or...
import math as _math

In larger projects this "best practice" allows my to exactly control what is disclosed to subsequent imports and what isn't. This keeps my modules clean and pays back at a certain size of project.

心凉 2024-07-23 05:19:54

因为很多人都在这里回答,但我只是尽力而为:)

  1. 当您不知道必须从 module 导入哪个项目时,

    import module 是最好的选择。 这样当问题出现时可能很难调试,因为
    您不知道哪个项目有问题。

  2. 当您知道需要导入哪个项目时,

    form module import 是最好的选择,并且还有助于根据您的需要使用导入特定项目进行更多控制。 使用这种方式调试可能会很容易,因为您知道导入了哪个项目。

since many people answered here but i am just trying my best :)

  1. import module is best when you don't know which item you have to import from module. In this way it may be difficult to debug when problem raises because
    you don't know which item have problem.

  2. form module import <foo> is best when you know which item you require to import and also helpful in more controlling using importing specific item according to your need. Using this way debugging may be easy because you know which item you imported.

路还长,别太狂 2024-07-23 05:19:54

导入模块 - 您不需要额外的努力来从模块中获取其他内容。 它有一些缺点,例如冗余输入

模块导入自 - 更少的输入和更多的控制可以访问模块的哪些项目。要使用模块中的新项目,您必须更新导入语句。

Import Module - You don't need additional efforts to fetch another thing from module. It has disadvantages such as redundant typing

Module Import From - Less typing &More control over which items of a module can be accessed.To use a new item from the module you have to update your import statement.

耶耶耶 2024-07-23 05:19:54

有一些内置模块主要包含裸函数(base64数学os, shutil systime, ...) 绑定这些裸函数绝对是一个好习惯 到某个命名空间,从而提高代码的可读性。 考虑一下在没有命名空间的情况下理解这些函数的含义

copysign(foo, bar)
monotonic()
copystat(foo, bar)

比它们绑定到某个模块时

math.copysign(foo, bar)
time.monotonic()
shutil.copystat(foo, bar)

要困难得多:有时您甚至需要命名空间来避免不同模块之间的冲突(json.loadpickle.load)


On the other hand there are some modules that contain mostly classes (configparser, datetime, tempfile, zipfile, ...) and many of them make their class names self-explanatory enough:

configparser.RawConfigParser()
datetime.DateTime()
email.message.EmailMessage()
tempfile.NamedTemporaryFile()
zipfile.ZipFile()

因此,在代码中使用这些类和附加模块命名空间是否会添加一些新信息或只是延长代码可能存在争议。

There are some builtin modules that contain mostly bare functions (base64, math, os, shutil, sys, time, ...) and it is definitely a good practice to have these bare functions bound to some namespace and thus improve the readability of your code. Consider how more difficult is to understand the meaning of these functions without their namespace:

copysign(foo, bar)
monotonic()
copystat(foo, bar)

than when they are bound to some module:

math.copysign(foo, bar)
time.monotonic()
shutil.copystat(foo, bar)

Sometimes you even need the namespace to avoid conflicts between different modules (json.load vs. pickle.load)


On the other hand there are some modules that contain mostly classes (configparser, datetime, tempfile, zipfile, ...) and many of them make their class names self-explanatory enough:

configparser.RawConfigParser()
datetime.DateTime()
email.message.EmailMessage()
tempfile.NamedTemporaryFile()
zipfile.ZipFile()

so there can be a debate whether using these classes with the additional module namespace in your code adds some new information or just lengthens the code.

季末如歌 2024-07-23 05:19:54

我正在回答类似的问题帖子,但发布者在我发帖之前将其删除。 这是一个例子来说明差异。

Python 库可能有一个或多个文件(模块)。 例如,

package1
  |-- __init__.py

我们

package2
  |-- __init__.py
  |-- module1.py
  |-- module2.py

可以在任何基于设计要求的文件中定义 python 函数或类。

让我们

  1. mylibrary1 下的 __init__.py 中定义 func1(),并
  2. module2 中定义 foo()。 pymylibrary2 下。

我们可以使用以下方法之一访问 func1()

import package1

package1.func1()

import package1 as my

my.func1()

or

from package1 import func1

func1()

or

from package1 import *

func1()

我们可以使用以下方法之一访问 foo()

import package2.module2

package2.module2.foo()

or

import package2.module2 as mod2

mod2.foo()

or

from package2 import module2

module2.foo()

or

from package2 import module2 as mod2

mod2.foo()

or

from package2.module2 import *

foo()

I was answering a similar question post but the poster deleted it before i could post. Here is one example to illustrate the differences.

Python libraries may have one or more files (modules). For exmaples,

package1
  |-- __init__.py

or

package2
  |-- __init__.py
  |-- module1.py
  |-- module2.py

We can define python functions or classes inside any of the files based design requirements.

Let's define

  1. func1() in __init__.py under mylibrary1, and
  2. foo() in module2.py under mylibrary2.

We can access func1() using one of these methods

import package1

package1.func1()

or

import package1 as my

my.func1()

or

from package1 import func1

func1()

or

from package1 import *

func1()

We can use one of these methods to access foo():

import package2.module2

package2.module2.foo()

or

import package2.module2 as mod2

mod2.foo()

or

from package2 import module2

module2.foo()

or

from package2 import module2 as mod2

mod2.foo()

or

from package2.module2 import *

foo()
你另情深 2024-07-23 05:19:54

简单来说,这都是为了程序员的方便。 在核心级别,他们只需导入模块的所有功能。

导入模块:当您使用导入模块时,要使用该模块的方法,您必须编写module.method(). 每次使用任何方法或属性时,都必须引用该模块。

from module import all:当您使用from module import all而不是使用此模块的方法时,您只需编写method( ) 而不引用模块。

In simple words, this is all about programmer convenience. At the core level, they simply import all functionality of the module.

import module: When you use import module then to use methods of this module you have to write module.method(). Every time you use any method or property then you have to refer to the module.

from module import all: When you use from module import all than to use methods of this module you just have to write method() without referring to the module.

你是我的挚爱i 2024-07-23 05:19:54

@ahfx 已经提到了这些导入的一个关键方面,即加载模块过程的内部结构。 如果您的系统需要使用循环导入(例如您想在一些流行的 http 框架中使用依赖注入),则会弹出此消息。 在这种情况下,from {module} import {function} 对加载过程如何进行的要求显得更加激进。 让我们举个例子:

#m1.py:
print('--start-m1--')
from m2 import *    # form does not matter; just need to force import of m2
print('--mid-m1--')

def do1(x):
    print(x)

print('--end-m1--')

importing

#m2.py
print('--start-m2--')

# from m1 import *      # A
# from m1 import do1    # B
# import m1             # C
                        # D -- no import of "do1" at all
                        
print('--mid-m2--')

def do2(x):
    m1.do1(x)

print('--end-m2--')

run via

#main.py:
from m1 import do1
do1('ok')

m2.py (A,B,C,D) 中的所有导入可能性中,from {module} import {function}唯一真正使加载过程崩溃的,导致臭名昭著的(CPython 3.10.6)

ImportError: cannot import name 'do1' from partially initialized module 'm1' 
(most likely due to a circular import)

虽然我不能说为什么会发生这种情况,但似乎是 from ... import 。 .. 语句对相关模块已经处于初始化过程中的“程度”提出了更严格的要求。

There is a crucial aspect of these imports that @ahfx already mentioned, namely the internals of the process of loading modules. This pops up if your system needs to use circular imports (e.g. you want to make use of dependency injection in some popular http frameworks). In such cases the from {module} import {function} appears much more aggressive with its requirements on how the loading process proceeds. Let us take the example:

#m1.py:
print('--start-m1--')
from m2 import *    # form does not matter; just need to force import of m2
print('--mid-m1--')

def do1(x):
    print(x)

print('--end-m1--')

importing

#m2.py
print('--start-m2--')

# from m1 import *      # A
# from m1 import do1    # B
# import m1             # C
                        # D -- no import of "do1" at all
                        
print('--mid-m2--')

def do2(x):
    m1.do1(x)

print('--end-m2--')

run via

#main.py:
from m1 import do1
do1('ok')

Of all the import possibilities in m2.py (A,B,C,D), the from {module} import {function} is the only one that actually crashes the load process, leading to the infamous (CPython 3.10.6)

ImportError: cannot import name 'do1' from partially initialized module 'm1' 
(most likely due to a circular import)

While I cannot say why this happens, it appears that the from ... import ... statement puts a more stringent requirement on "how far" the module in question is already in its initialization process.

木緿 2024-07-23 05:19:53

import modulefrom module import foo 之间的区别主要是主观的。 选择您最喜欢的一个并在使用过程中保持一致。 以下几点可以帮助您做出决定。

导入模块

  • 优点:
    • 减少 import 语句的维护。 不需要添加任何额外的导入即可开始使用模块中的另一个项目
  • 缺点:
    • 在代码中输入 module.foo 可能会很乏味且多余(可以通过使用 import module as mo 然后输入 mo.foo 来最大程度地减少乏味。代码>)

from module import foo

  • 优点:
    • 使用 foo 减少输入
    • 更好地控制可以访问模块的哪些项目
  • 缺点:
    • 要使用模块中的新项目,您必须更新 import 语句
    • 您失去了有关 foo 的上下文。 例如,与 math.ceil() 相比,ceil() 的作用不太清楚

两种方法都可以接受,但不要使用 <代码>从模块导入*。

对于任何合理的大型代码集,如果您import *,您可能会将其固定到模块中,无法删除。 这是因为很难确定代码中使用的哪些项目来自“模块”,因此很容易达到您认为不再使用 import 但实际上是这样的地步。很难确定。

The difference between import module and from module import foo is mainly subjective. Pick the one you like best and be consistent in your use of it. Here are some points to help you decide.

import module

  • Pros:
    • Less maintenance of your import statements. Don't need to add any additional imports to start using another item from the module
  • Cons:
    • Typing module.foo in your code can be tedious and redundant (tedium can be minimized by using import module as mo then typing mo.foo)

from module import foo

  • Pros:
    • Less typing to use foo
    • More control over which items of a module can be accessed
  • Cons:
    • To use a new item from the module you have to update your import statement
    • You lose context about foo. For example, it's less clear what ceil() does compared to math.ceil()

Either method is acceptable, but don't use from module import *.

For any reasonable large set of code, if you import * you will likely be cementing it into the module, unable to be removed. This is because it is difficult to determine what items used in the code are coming from 'module', making it easy to get to the point where you think you don't use the import any more but it's extremely difficult to be sure.

¢蛋碎的人ぎ生 2024-07-23 05:19:53

这里还有一个未提及的细节,与写入模块有关。 当然这可能不是很常见,但我时不时需要它。

由于引用和名称绑定在 Python 中的工作方式,如果您想从模块外部更新模块中的某些符号(例如 foo.bar),并且让其他导入代码“看到”该更改,则必须导入 foo某种方式。 例如:

module foo:

bar = "apples"

module a:

import foo
foo.bar = "oranges"   # update bar inside foo module object

module b:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

但是,如果导入符号名称而不是模块名称,则这将不起作用。

例如,如果我在模块 a 中执行此操作:

from foo import bar
bar = "oranges"

a 之外的任何代码都不会将 bar 视为“橙子”,因为我的 bar 设置仅仅是影响了模块a内的名称“bar”,它没有“到达”foo模块对象并更新其bar

There's another detail here, not mentioned, related to writing to a module. Granted this may not be very common, but I've needed it from time to time.

Due to the way references and name binding works in Python, if you want to update some symbol in a module, say foo.bar, from outside that module, and have other importing code "see" that change, you have to import foo a certain way. For example:

module foo:

bar = "apples"

module a:

import foo
foo.bar = "oranges"   # update bar inside foo module object

module b:

import foo           
print foo.bar        # if executed after a's "foo.bar" assignment, will print "oranges"

However, if you import symbol names instead of module names, this will not work.

For example, if I do this in module a:

from foo import bar
bar = "oranges"

No code outside of a will see bar as "oranges" because my setting of bar merely affected the name "bar" inside module a, it did not "reach into" the foo module object and update its bar.

小梨窩很甜 2024-07-23 05:19:53

尽管很多人已经解释了 importimport from,但我想尝试更多地解释一下幕后发生的事情,以及它更改的所有地方。


import foo

导入foo,并在当前命名空间中创建对该模块的引用。 然后,您需要定义完整的模块路径以从模块内部访问特定属性或方法。

例如 foo.bar 但不是 bar

from foo import bar

导入 foo,并创建对所有成员的引用列出()。 不设置变量foo

例如 bar 但不是 bazfoo.baz

from foo import *

导入 foo,并创建对该模块在当前命名空间中定义的所有公共对象的引用(如果 __all__ 存在,则在 __all__ 中列出所有内容,否则不以 开头的所有内容>_)。 不设置变量foo

例如 barbaz,但不是 _quxfoo._qux


现在让我们看看何时 import XY

>>> import sys
>>> import os.path

检查名称为 osos.pathsys.modules

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

检查globals()locals() 命名空间字典以及 osos.path

>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>

从上面的例子中我们发现只有 os 被插入到本地和全局命名空间中。
所以,我们应该能够使用:

>>> os
<module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

但不能使用path

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

一旦您从 locals() 命名空间中删除了 os,您将无法访问 os 以及 os.path,即使它们存在于 sys.modules 中:

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

现在我们来谈谈 import from

from

>>> import sys
>>> from os import path

os 检查 sys.modulesos.path

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

我们发现在sys.modules中我们发现与之前使用import name相同的内容,

好的,让我们检查一下它是如何实现的看起来像在 locals()globals() 命名空间字典中:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

您可以使用名称 path 访问,而不是通过 os.path< /code>:

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

让我们从 locals() 中删除“路径”:

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

最后一个使用别名的示例:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

并且没有定义路径:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

Even though many people already explained about import vs import from, I want to try to explain a bit more about what happens under the hood, and where all the places it changes are.


import foo:

Imports foo, and creates a reference to that module in the current namespace. Then you need to define completed module path to access a particular attribute or method from inside the module.

E.g. foo.bar but not bar

from foo import bar:

Imports foo, and creates references to all the members listed (bar). Does not set the variable foo.

E.g. bar but not baz or foo.baz

from foo import *:

Imports foo, and creates references to all public objects defined by that module in the current namespace (everything listed in __all__ if __all__ exists, otherwise everything that doesn't start with _). Does not set the variable foo.

E.g. bar and baz but not _qux or foo._qux.


Now let’s see when we do import X.Y:

>>> import sys
>>> import os.path

Check sys.modules with name os and os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

Check globals() and locals() namespace dicts with os and os.path:

>>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>

From the above example we found that only os is inserted in the local and global namespace.
So, we should be able to use:

>>> os
<module 'os' from
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> os.path
<module 'posixpath' from
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

But not path.

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

Once you delete the os from locals() namespace, you won't be able to access os as well as os.path even though they exist in sys.modules:

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Now let's talk about import from:

from:

>>> import sys
>>> from os import path

Check sys.modules with os and os.path:

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

We found that in sys.modules we found as same as we did before by using import name

OK, let's check how it looks like in locals() and globals() namespace dicts:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

You can access by using name path not by os.path:

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

Let's delete 'path' from locals():

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

One final example using an alias:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

And no path defined:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>
小女人ら 2024-07-23 05:19:53

这两种方式都受到支持是有原因的:有时一种方式比另一种方式更合适。

  • 导入模块:当您使用模块中的许多位时,这很好。 缺点是您需要使用模块名称来限定每个引用。

  • from module import ...:很高兴导入的项目可以直接使用,无需模块名称前缀。 缺点是你必须列出你使用的每一个东西,并且在代码中不清楚东西来自哪里。

使用哪个取决于哪个使代码清晰易读,并且与个人喜好有很大关系。 我通常倾向于导入模块,因为在代码中,对象或函数的来源非常清楚。 当我在代码中大量使用某些对象/函数时,我会使用 from module import ...

Both ways are supported for a reason: there are times when one is more appropriate than the other.

  • import module: nice when you are using many bits from the module. drawback is that you'll need to qualify each reference with the module name.

  • from module import ...: nice that imported items are usable directly without module name prefix. The drawback is that you must list each thing you use, and that it's not clear in code where something came from.

Which to use depends on which makes the code clear and readable, and has more than a little to do with personal preference. I lean toward import module generally because in the code it's very clear where an object or function came from. I use from module import ... when I'm using some object/function a lot in the code.

凡间太子 2024-07-23 05:19:53

我个人总是使用

from package.subpackage.subsubpackage import module

并访问所有内容,等等

module.function
module.modulevar

。原因是,同时您的调用很短,并且您清楚地定义了每个例程的模块名称空间,如果您必须搜索给定的使用情况,这非常有用源中的模块。

不用说,不要使用 import *,因为它会污染你的命名空间,并且它不会告诉你给定的函数来自哪里(来自哪个模块)

当然,如果两个模块名称相同,你可能会遇到麻烦不同的模块位于两个不同的包中,就像

from package1.subpackage import module
from package2.subpackage import module

在这种情况下,当然你会遇到麻烦,但是强烈暗示你的包布局有缺陷,你必须重新考虑它。

I personally always use

from package.subpackage.subsubpackage import module

and then access everything as

module.function
module.modulevar

etc. The reason is that at the same time you have short invocation, and you clearly define the module namespace of each routine, something that is very useful if you have to search for usage of a given module in your source.

Needless to say, do not use the import *, because it pollutes your namespace and it does not tell you where a given function comes from (from which module)

Of course, you can run in trouble if you have the same module name for two different modules in two different packages, like

from package1.subpackage import module
from package2.subpackage import module

in this case, of course you run into troubles, but then there's a strong hint that your package layout is flawed, and you have to rethink it.

仅一夜美梦 2024-07-23 05:19:53
import module

当您将使用模块中的许多功能时这是最好的选择。

from module import function

当您只需要 function 时,如果您想避免模块中的所有函数和类型污染全局命名空间,这是最好的选择。

import module

Is best when you will use many functions from the module.

from module import function

Is best when you want to avoid polluting the global namespace with all the functions and types from a module when you only need function.

陪我终i 2024-07-23 05:19:53

我刚刚发现这两种方法之间的一个更微妙的区别。

如果模块 foo 使用以下导入:

from itertools import count

那么模块 bar 可能会错误地使用 count,就好像它是在 foo,不在 itertools 中:

import foo
foo.count()

如果 foo 使用:

import itertools

错误仍然有可能,但不太可能发生。 bar need to:

import foo
foo.itertools.count()

这给我带来了一些麻烦。 我有一个模块错误地从一个没有定义它的模块导入了一个异常,只是从其他模块导入了它(使用 from module import SomeException)。 当不再需要并删除导入时,有问题的模块就被破坏了。

I've just discovered one more subtle difference between these two methods.

If module foo uses a following import:

from itertools import count

Then module bar can by mistake use count as though it was defined in foo, not in itertools:

import foo
foo.count()

If foo uses:

import itertools

the mistake is still possible, but less likely to be made. bar needs to:

import foo
foo.itertools.count()

This caused some troubles to me. I had a module that by mistake imported an exception from a module that did not define it, only imported it from other module (using from module import SomeException). When the import was no longer needed and removed, the offending module was broken.

诗笺 2024-07-23 05:19:53

这里还有一个没有提到的区别。 这是从 http://docs.python.org/2/tutorial/modules 逐字复制的。请

注意,使用时

from package import item

该项目可以是包的子模块(或子包),也可以是包中定义的其他名称,例如函数、类或变量。 import语句首先测试包中是否定义了该项; 如果不是,它假设它是一个模块并尝试加载它。 如果找不到它,则会引发 ImportError 异常。

相反,当使用语法时,

import item.subitem.subsubitem

除了最后一项之外的每个项目都必须是一个包; 最后一项可以是模块或包,但不能是前一项中定义的类、函数或变量。

Here is another difference not mentioned. This is copied verbatim from http://docs.python.org/2/tutorial/modules.html

Note that when using

from package import item

the item can be either a submodule (or subpackage) of the package, or some other name defined in the package, like a function, class or variable. The import statement first tests whether the item is defined in the package; if not, it assumes it is a module and attempts to load it. If it fails to find it, an ImportError exception is raised.

Contrarily, when using syntax like

import item.subitem.subsubitem

each item except for the last must be a package; the last item can be a module or a package but can’t be a class or function or variable defined in the previous item.

行雁书 2024-07-23 05:19:53

由于我也是初学者,所以我将尝试以简单的方式解释这一点:
在 Python 中,我们有三种类型的 import 语句,它们是:

1. 通用导入:

import math

这种类型的导入是我个人最喜欢的,这种导入技术的唯一缺点是,如果您需要使用任何模块的功能,则必须使用以下语法:

math.sqrt(4)

of当然,它会增加打字工作量,但作为初学者,它将帮助您跟踪与其相关的模块和功能(良好的文本编辑器将显着减少打字工作量,建议使用)。

使用此导入语句可以进一步减少输入工作量:

import math as m

现在,您可以使用 m 而不是使用 math.sqrt() .sqrt().

2. 函数导入:

from math import sqrt

如果您的代码只需要访问模块中的单个或几个函数,则这种类型的导入最适合,但要使用模块中的任何新项,您必须更新导入语句。 em>

3。 通用导入:

from math import * 

虽然它显着减少了打字工作,但不推荐,因为它会用模块中的各种函数填充您的代码,并且它们的名称可能与用户定义函数的名称冲突。
示例:

如果您有一个自己命名的 sqrt 函数并且导入了 math,则您的函数是安全的:有您的 sqrt,也有 math.sqrt。 但是,如果您执行 from math import * 操作,则会遇到一个问题:即两个不同的函数具有完全相同的名称。 来源:Codecademy

Since I am also a beginner, I will be trying to explain this in a simple way:
In Python, we have three types of import statements which are:

1. Generic imports:

import math

this type of import is my personal favorite, the only downside to this import technique is that if you need use any module's function you must use the following syntax:

math.sqrt(4)

of course, it increases the typing effort but as a beginner, it will help you to keep track of module and function associated with it, (a good text editor will reduce the typing effort significantly and is recommended).

Typing effort can be further reduced by using this import statement:

import math as m

now, instead of using math.sqrt() you can use m.sqrt().

2. Function imports:

from math import sqrt

this type of import is best suited if your code only needs to access single or few functions from the module, but for using any new item from the module you have to update import statement.

3. Universal imports:

from math import * 

Although it reduces typing effort significantly but is not recommended because it will fill your code with various functions from the module and their name could conflict with the name of user-defined functions.
example:

If you have a function of your very own named sqrt and you import math, your function is safe: there is your sqrt and there is math.sqrt. If you do from math import *, however, you have a problem: namely, two different functions with the exact same name. Source: Codecademy

尴尬癌患者 2024-07-23 05:19:53

我想补充一下。 如果遇到循环导入,了解 Python 如何将导入的模块作为属性处理会很有用。

我有以下结构:

mod/
    __init__.py
    main.py
    a.py
    b.py
    c.py
    d.py

从 main.py 我将使用不同的导入方法导入其他模块

main.py:

import mod.a
import mod.b as b
from mod import c
import d

dis.dis 显示差异(注意模块名称,abcd):

  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (mod.a)
              9 STORE_NAME               1 (mod)

  2          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              2 (b)
             21 STORE_NAME               2 (b)

  3          24 LOAD_CONST               0 (-1)
             27 LOAD_CONST               2 (('c',))
             30 IMPORT_NAME              1 (mod)
             33 IMPORT_FROM              3 (c)
             36 STORE_NAME               3 (c)
             39 POP_TOP

  4          40 LOAD_CONST               0 (-1)
             43 LOAD_CONST               1 (None)
             46 IMPORT_NAME              4 (mod.d)
             49 LOAD_ATTR                5 (d)
             52 STORE_NAME               5 (d)
             55 LOAD_CONST               1 (None)

最后它们看起来相同(STORE_NAME 的结果是每个示例),但如果您需要考虑以下四个循环导入,则值得注意:

example1

foo/
   __init__.py
   a.py
   b.py
a.py:
import foo.b 
b.py:
import foo.a
>>> import foo.a
>>>

这有效

example2

bar/
   __init__.py
   a.py
   b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bar\a.py", line 1, in <module>
    import bar.b as b
  File "bar\b.py", line 1, in <module>
    import bar.a as a
AttributeError: 'module' object has no attribute 'a'

无骰子

example3

baz/
   __init__.py
   a.py
   b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "baz\a.py", line 1, in <module>
    from baz import b
  File "baz\b.py", line 1, in <module>
    from baz import a
ImportError: cannot import name a

不同

类似的问题...但显然 from x import y 与 import import xy as y example4

qux/
   __init__.py
   a.py
   b.py
a.py:
import b 
b.py:
import a
>>> import qux.a
>>>

这 一个也有效

I would like to add to this. It can be useful to understand how Python handles imported modules as attributes if you run into circular imports.

I have the following structure:

mod/
    __init__.py
    main.py
    a.py
    b.py
    c.py
    d.py

From main.py I will import the other modules using differnt import methods

main.py:

import mod.a
import mod.b as b
from mod import c
import d

dis.dis shows the difference (note module names, a b c d):

  1           0 LOAD_CONST               0 (-1)
              3 LOAD_CONST               1 (None)
              6 IMPORT_NAME              0 (mod.a)
              9 STORE_NAME               1 (mod)

  2          12 LOAD_CONST               0 (-1)
             15 LOAD_CONST               1 (None)
             18 IMPORT_NAME              2 (b)
             21 STORE_NAME               2 (b)

  3          24 LOAD_CONST               0 (-1)
             27 LOAD_CONST               2 (('c',))
             30 IMPORT_NAME              1 (mod)
             33 IMPORT_FROM              3 (c)
             36 STORE_NAME               3 (c)
             39 POP_TOP

  4          40 LOAD_CONST               0 (-1)
             43 LOAD_CONST               1 (None)
             46 IMPORT_NAME              4 (mod.d)
             49 LOAD_ATTR                5 (d)
             52 STORE_NAME               5 (d)
             55 LOAD_CONST               1 (None)

In the end they look the same (STORE_NAME is result in each example), but this is worth noting if you need to consider the following four circular imports:

example1

foo/
   __init__.py
   a.py
   b.py
a.py:
import foo.b 
b.py:
import foo.a
>>> import foo.a
>>>

This works

example2

bar/
   __init__.py
   a.py
   b.py
a.py:
import bar.b as b
b.py:
import bar.a as a
>>> import bar.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "bar\a.py", line 1, in <module>
    import bar.b as b
  File "bar\b.py", line 1, in <module>
    import bar.a as a
AttributeError: 'module' object has no attribute 'a'

No dice

example3

baz/
   __init__.py
   a.py
   b.py
a.py:
from baz import b
b.py:
from baz import a
>>> import baz.a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "baz\a.py", line 1, in <module>
    from baz import b
  File "baz\b.py", line 1, in <module>
    from baz import a
ImportError: cannot import name a

Similar issue... but clearly from x import y is not the same as import import x.y as y

example4

qux/
   __init__.py
   a.py
   b.py
a.py:
import b 
b.py:
import a
>>> import qux.a
>>>

This one also works

柏拉图鍀咏恒 2024-07-23 05:19:53
import package
import module

使用 import 时,令牌必须是模块(包含 Python 命令的文件)或包(sys.path 中包含文件 __init__.py 的文件夹)。)

当有子包时:

import package1.package2.package
import package1.package2.module

文件夹(包)或文件(模块)的要求相同,但文件夹或文件必须位于package2内,而package2必须位于内package1,并且 package1package2 都必须包含 __init__.py 文件。 https://docs.python.org/2/tutorial/modules.html

使用 from 风格的导入:

from package1.package2 import package
from package1.package2 import module

包或模块进入包含 import 语句的文件的命名空间作为 module (或 package)而不是package1.package2.module。 您始终可以绑定到更方便的名称:

a = big_package_name.subpackage.even_longer_subpackage_name.function

只有 from 样式的导入允许您命名特定的函数或变量:

from package3.module import some_function

允许,但

import package3.module.some_function 

不允许。

import package
import module

With import, the token must be a module (a file containing Python commands) or a package (a folder in the sys.path containing a file __init__.py.)

When there are subpackages:

import package1.package2.package
import package1.package2.module

the requirements for folder (package) or file (module) are the same, but the folder or file must be inside package2 which must be inside package1, and both package1 and package2 must contain __init__.py files. https://docs.python.org/2/tutorial/modules.html

With the from style of import:

from package1.package2 import package
from package1.package2 import module

the package or module enters the namespace of the file containing the import statement as module (or package) instead of package1.package2.module. You can always bind to a more convenient name:

a = big_package_name.subpackage.even_longer_subpackage_name.function

Only the from style of import permits you to name a particular function or variable:

from package3.module import some_function

is allowed, but

import package3.module.some_function 

is not allowed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文