Python中import的细节

防忘系列...

Pycharm并没有IDEA一样可以设置对import进行排序以及自动消除没用到的库(要用快捷键Ctrl + Alt + O), 并且如果导入方式不正确会 1.找不到自定义包 2.Pycharm对指定内容报错(下划线或红线)

Python中模块,包,库概念

模块:就是<u>.py文件</u>,里面定义了一些函数和变量,需要的时候就可以导入这些模块。

:在模块之上的概念,为了方便管理而将文件进行打包。包目录下第一个文件便是__init__.py,然后是一些模块文件和子目录,假如子目录中也有__init__.py,那么它就是这个包的子包了。

:具有相关功能模块、包的集合。这也是Python的一大特色之一,即具有强大的标准库、第三方库以及自定义模块。

标准库:就是下载安装的python里那些自带的模块,要注意的是,里面有一些模块是看不到的比如像sys模块,这与linux下的cd命令看不到是一样的情况。

第三方库:就是由其他的第三方机构,发布的具有特定功能的模块。

自定义模块:用户自己可以自行编写模块,然后使用。

总结: 我们pip install <package>安装的是库,库下有很多包,我们在自己的项目文件中import有以下几种用法:

  • import numpy as np
  • import urllib.parse import urlencode
  • from lxml import HTML

之前大家应该碰到过,命名自己pip install xx安装的是叫xx的库,但是在用的时候写的却是from yy import zz,明显不对应嘛。因此,其实库和包的区别还可以通过setup.py打包成库来看。——使用setup.py打包python文件Python实现打包成库供别的模块调用

其中比较重要的就是5.编写:setup.py

注意:setup.py与要打包的test_package包同在bricewulib根目录下。

其中比较重要的几项是:name,version,packages

  • name:描述的是你打包的文件夹名。
  • version描述的是文件的版本号。
  • packages是所有要打包的包(package),这里需要打包的是test_package包以及test_package包下的test_package。输入python setup.py sdist然后就能创建bricewulib库,使用test_package包
setup(
    name = "bricewulib",
    version = "1.0",
    packages=["test_package","test_package.test_package2"]
)

import推荐顺序

我们推荐所有的模块在 Python 模块的开头部分导入。 而且最好按照这样的顺序:

  1. Python 标准库模块
  2. Python 第三方模块
  3. 应用程序自定义模块

通过空行来分割——(Python's Style Guide), PEP8 。

import的搜索顺序:

  1. 首先判断这个module是不是built-in即内建模块,如果是则引入内建模块,如果不是则在一个称为sys.path的list中寻找
  2. sys.path在python脚本执行时动态生成,包括以下3个部分:
  • 脚本执行的位置,即当前路径
  • 环境变量中的PYTHONPATH, 即.bash_profilec.
  • 安装python时的依赖位置

Python的import机制

运行、编写Python代码时,一定要注意的是脚本路径和脚本执行路径,以及相对路径和绝对路径

如果在项目中运用了相对路径,则一定要注意脚本执行路径

假设A是B的父目录, 如我们想在A目录调用B中模块, 而B中模板是又import了A下模板, 如login: from login import ftSession命令行在A路径下输入python B/main.py时, 会报错。因为import其实就是在搜索目录下按相对路径找的。

Pycharm的坑:

借鉴: Python的import机制坑在哪?

pycharm里打出来的路径是更多的,它把项目根目录加进去了。(也可以设置: 进入设置,找到Console下的Python Console,勾选选项“Add source roots to PYTHONPAT” )

查看搜索路径:print(sys.path)

settings.jpg

What's resource root?

Source roots (or source folders; shown asm).
These roots contain the actual source files and resources. PyCharm uses the source roots as the starting point for resolving imports.
The files under the source roots are interpreted according to their type. PyCharm can parse, inspect, index, and compile the contents of these roots.

以上导致的问题就是:

pycharm中,project folder是默认的source root,当你使用import语句导入模块时,Pycharm默认在project folder中寻找;所以当你在project folder下的某个subfolder导入某个同样定义在这个subfolder中的模块时,会出现导入错误。

pycharm中的第一个文件夹,即代表项目, 当在其中再次建立文件夹时,是按package处理的

如果要在这些文件夹内import其他文件,需要将完整路径导入进来

所以最终在Pycharm中导入的方式有两种: burning回答

  • 从project folder开始相对导入
  • 将module文件夹直接定义为source root

pycharm在同目录下import划红线但实际可以运行

解决方法: 右键将model所在的文件夹设置为source root

总结:python该如何import

需要明确的一点是:在运行Python脚本的时候,Python解释器会把脚本执行的位置,即当前路径加入到搜索路径中,而绝大多数情况main函数就在工程根目录,因此对于一个工程而言,最好的是从从project folder(工程根目录,即运行main函数的那个入口文件)开始相对导入

▲需要注意的是,对于main函数如果不在根目录,而是在工程目录的子目录中的情况,需要在main.py中自己手动添加sys.path.append(".."),即想办法把工程根目录加到搜索目录中,这样以后就可以又开始从工程根目录开始import了。

还有一个对于初学者可能会产生自我怀疑的点,我也顺便提一下好了

from config import *
// 等价于
from .config import *

__init__文件作用

在Python工程里,当python检测到一个目录下存在__init__.py文件时,python就会把这个目录当成一个包(package)。Module跟C++的命名空间和Java的Package的概念很像,都是为了科学地组织化工程,管理命名空间。

__init__.py的设计原则

__init__.py的原始使命是声明一个模块,所以它可以是一个空文件。

A、不要污染现有的命名空间。模块一个目的,是为了避免命名冲突,如果你在种用init.py时违背这个原则,是反其道而为之,就没有必要使用模块了。

B、利用__init__.py外提供类型、变量和接口,对用户隐藏各个子模块的实现。一个模块的实现可能非常复杂,你需要用很多个文件,甚至很多子模块来实现,但用户可能只需要知道一个类型和接口。就像我们的arithmetic例子中,用户只需要知道四则运算有add、sub、mul、dev四个接口,却并不需要知道它们是怎么实现的,也不想去了解arithmetic中是如何组织各个子模块的。由于各个子模块的实现有可能非常复杂,而对外提供的类型和接口有可能非常的简单,我们就可以通过这个方式来对用户隐藏实现,同时提供非常方便的使用。

C、只在init.py中导入有必要的内容,不要做没必要的运算。像我们的例子,import arithmetic语句会执行__ini__.py中的所有代码。如果我们在__init__.py中做太多事情,每次import都会有额外的运算,会造成没有必要的开销。一句话,init.py只是为了达到B中所表述的目的,其它事情就不要做啦。

上述来自: https://zhuanlan.zhihu.com/p/115350758

__all__变量

__all__是一个字符串list;

约束作用:用来定义模块中对于from XXX import *时要对外导出的符号,即要暴露的借口,但它只对import *起作用(即如果在使用脚本中对当前包使用import *,那么可以管理当前包下模块的导入情况),对from XXX import XXX不起作用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 当前目录 和 脚本目录 参考资料:https://techibee.com/python/get-current-...
    ThomasYoungK阅读 11,422评论 0 11
  • 模块和包 一 模块 1 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是...
    go以恒阅读 2,307评论 0 4
  • 1. 函数的定义与使用 1.1 函数的定义 1.2 函数的基本调用 1.3 函数的使用技巧(==IMPORTANT...
    c0b2b66e5dc4阅读 276评论 0 1
  • A:概念解释: 模块:.py文件 包:一个目录结构,包含__init__.py文件的目录 库:完成一定功能的代码集...
    hello_我的哥阅读 654评论 0 1
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,584评论 16 22