关于包导入,这三个知识点太多人不知道了

开发 前端
使用 from module import * 默认情况下会导入 module 里的所有变量,若你只想从模块中导入其中几个变量,可以在 module 中使用 __all__ 来控制想要被其他模块导入的变量。

 [[374236]]

1. 使用 __all__ 控制可被导入的变量

使用 from module import * 默认情况下会导入 module 里的所有变量,若你只想从模块中导入其中几个变量,可以在 module 中使用 __all__ 来控制想要被其他模块导入的变量。

  1. # profile.py 
  2. name='小明' 
  3. age=18 
  4.  
  5. __all__=['name'

打开 python console 验证一下

  1. >>> from profile import * 
  2. >>> print(name
  3. 小明 
  4. >>> print(age) 
  5. Traceback (most recent call last): 
  6.   File "<stdin>", line 1, in <module> 
  7. NameError: name 'age' is not defined 

__all__ 仅对于使用from module import * 这种情况适用。

它经常在一个包的 __init__.py 中出现。

2. 命名空间包的神奇之处

命名空间包,对于不少人来说,可能是一个陌生的名字。

与我们熟悉的常规包不同的是,它没有 __init__.py 文件。

更为特殊的是,它可以跨空间地将两个不相邻的子包,合并成一个虚拟机的包,我们将其称之为 命名空间包。

例如,一个项目的部分代码布局如下

  1. foo-package/ 
  2.     spam/ 
  3.         blah.py 
  4.  
  5. bar-package/ 
  6.     spam/ 
  7.         grok.py 

在这2个目录里,都有着共同的命名空间spam。在任何一个目录里都没有__init__.py文件。

让我们看看,如果将foo-package和bar-package都加到python模块路径并尝试导入会发生什么?

  1. >>> import sys 
  2. >>> sys.path.extend(['foo-package''bar-package']) 
  3. >>> import spam.blah 
  4. >>> import spam.grok 
  5. >>> 

当一个包为命名空间包时,他就不再和常规包一样具有 __file_ 属性,取而代之的是 __path__

  1. >>> import sys 
  2. >>> sys.path.extend(['foo-package''bar-package']) 
  3. >>> import spam.blah 
  4. >>> import spam.grok 
  5. >>> spam.__path__ 
  6. _NamespacePath(['foo-package/spam''bar-package/spam']) 
  7. >>> spam.__file__ 
  8. Traceback (most recent call last): 
  9.     File "<stdin>", line 1, in <module> 
  10. AttributeError: 'module' object has no attribute '__file__' 

3. 模块重载中的一个坑

由于有 sys.modules 的存在,当你导入一个已导入的模块时,实际上是没有效果的。

为了达到模块的重载,有的人会将已导入的包从 sys.modules 中移除后再导入

就像下面这样子

  1. >>> import foo.bar 
  2. successful to be imported 
  3. >>> 
  4. >>> import foo.bar 
  5. >>> 
  6. >>> import sys 
  7. >>> sys.modules['foo.bar'
  8. <module 'foo.bar' from '/Users/MING/Code/Python/foo/bar.py'
  9. >>> del sys.modules['foo.bar'
  10. >>> 
  11. >>> import foo.bar 
  12. successful to be imported 

上面的例子里我使用的是import foo.bar ,如果你使用的是 from foo import bar 这种导入形式,会发现重载是同样是无效的。

这应该算是一个小坑,不知道的人,会掉入坑中爬不出来。

  1. >>> import foo.bar 
  2. successful to be imported 
  3. >>> 
  4. >>> import foo.bar 
  5. >>> 
  6. >>> import sys 
  7. >>> del sys.modules['foo.bar'
  8. >>> from foo import bar 
  9. >>> 

因此,在生产环境中可能需要避免重新加载模块。而在调试模式中,它会提供一定的便利,但你要知道这个重载的弊端,以免掉入坑里。

本文转载自微信公众号「Python编程时光」,可以通过以下二维码关注。转载本文请联系Python编程时光公众号。

 

责任编辑:武晓燕 来源: Python编程时光
相关推荐

2019-10-09 10:21:20

负载均衡架构开发

2011-08-16 13:15:15

MongoDB

2021-01-15 05:39:13

HashMapHashTableTreeMap

2020-06-29 08:28:36

v-for 解构函数

2022-10-27 21:01:03

JavaScrip面试题开发

2020-09-17 13:44:58

Python开源软件

2020-07-14 08:43:54

VueHTML函数

2021-02-24 09:45:21

数据库工具技术

2021-08-24 00:13:23

Windows 10Windows微软

2020-10-09 11:30:07

Redis缓存数据库

2015-07-22 11:53:29

云计算AWS分析瘫痪

2022-06-23 13:13:36

GitHub开发技巧

2019-01-07 09:27:39

2021-10-09 16:13:40

5G4G手机

2020-06-12 07:36:33

Redis

2021-01-12 12:33:20

Pandas技巧代码

2020-02-07 09:59:29

Python异常处理语言

2017-01-06 10:07:39

Linuxwindowsatime

2021-08-29 23:22:05

iPhone手机安卓

2021-11-02 19:14:58

Spring数据
点赞
收藏

51CTO技术栈公众号