防忘系列...
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 模块的开头部分导入。 而且最好按照这样的顺序:
- Python 标准库模块
- Python 第三方模块
- 应用程序自定义模块
通过空行来分割——(Python's Style Guide), PEP8 。
import的搜索顺序:
- 首先判断这个module是不是built-in即内建模块,如果是则引入内建模块,如果不是则在一个称为sys.path的list中寻找
- 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的坑:
pycharm里打出来的路径是更多的,它把项目根目录加进去了。(也可以设置: 进入设置,找到Console下的Python Console,勾选选项“Add source roots to PYTHONPAT” )
查看搜索路径:print(sys.path)
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
不起作用。