我是靠谱客的博主 尊敬刺猬,最近开发中收集的这篇文章主要介绍py “类,模块,包与库“ 的 import 机制概念明确import 导入机制PYTHONPATH参考,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 概念明确
    • 1.1 模块
    • 1.2 包
    • 1.3 库
  • import 导入机制
    • import 模块 语法
    • from 模块 import 变量 语法
    • 相对导入语法
    • 循环依赖错误
    • 与java的import对比
    • 自有项目内的模块 import
  • PYTHONPATH
  • 参考

模块, 包, 库的概念经常被混用. 只有明确概念, 指代清晰, 才能顺畅遨游python世界.

概念明确

1.1 模块

源文件即模块. 内含若干个类,函数,变量 (因为py不是完全的面向对象).
xxxmodule.__file__ # 查看模块的文件位置(绝对路径).
dir('xxxmodule') #查看模块中的函数等
自己写一个py源文件, 它的名字就是模块名, 可以被其他源文件 import .

1.2 包

包是一个含有__init__.py模块的特殊目录, 且内含若干个模块和若干个子目录.
__init__.py 可以只是一个空文件,但是必须存在; 否则就仅仅是普通目录,不能被其他模块导入与依赖.
有些IDE可能会不作严格检查, 但为了各个环境都能预期工作, 还是要确保.

所以包有两种角色: 包目录包模块.

1.3 库

库是相关包的集合. 如numpy, tensorflow.

import 导入机制

每种编程语言都有 import 机制来完成对 {类,变量,函数} 的依赖.

import 模块 语法

  • import 包模块 [as 别名]
  • import 包目录.子包目录.子包目录.包模块 [as 别名]

引入依赖是为了编码使用, 使用时的语法是 x=模块.变量
仔细揣摩一下两块代码片.

# import 片段1
import a 
# 引入的是 a/__init__.py, 会找变量b
# 情况1, b是模块, 即 __init__.py 中有 from xx import b, 那找的就是b模块下的c
# 情况2, b是类, 那找的就是b类的成员变量
a.b.c

典型的例子是

import numpy as np 
# numpy/__init__.py 中有from . import random
np.random

–分隔–

# import 片段2
import a.b.c
# 引入的是 /a/b/c/__init__.py
a.b.c

Q: __init__.py中的变量与子目录重名怎么办?
A: todo.

from 模块 import 变量 语法

为了编码时不再写长长的模块名, 可以用 from…import… 语法.

  • from 模块 import 类/方法/变量 [as 别名]
  • from 目录.子目录.子目录.模块 import 类/方法 [as 别名]
    此时使用时的语法是 x=变量
  • from 目录.子目录.子目录.模块 import *
    引入模块下所有变量.
    当模块有 __all__=[ 'var1','var2'] 变量时, 只会导入指定的变量.

pep标准推荐使用第一种方式,请在日常使用中尽量使用第一种方法,就比如numpy中random 标准库中也有random,但是两者的功能是不同的,使用第二种方式容易造成混淆.

相对导入语法

形如 from . import Bfrom ..A import B,理解为从 工作目录 作相对路径的导入.
.代表当前模块,..代表上层模块,...代表上上层模块,依次类推。

循环依赖错误

多个模块间使用from xx import xx这种语法引入循环依赖时, 会报错, 因为解释器都还没有执行到函数定义的代码,所以找不到模块。
解决办法为 使用 import xx 的语法, 不以from xx打头.

与java的import对比

  • import 语法
    java导入的只能是类, 清晰且严格.
    python 可以引入包,模块,类,方法,易混淆.
  • import 运行机制
    java只是声明一下用到的类的地址. 并没有把类的定义搬过来的效果.
    python 的import, 有着把引用的模块搬到了当前源文件里的效果. 这是一个我不喜欢的地方.
    比如 A 模块有了import numpy as np的语句, 那么B模块import A, 就可以通过A.np用 np 模块了, 别人看的时候就根本不知道np是一个顶级的包了.

自有项目内的模块 import

建议入口文件在 项目根目录下.
因为

  1. python解释器会将入口文件所在的目录自动添加到 PYHTONPATH .
  2. IDE 设置也方便.

PYTHONPATH

上文只是讲语法, 从哪里找要导入的模块呢? 从 PYTHONPATH 中找.

PYTHONPATH 并不是OS的环境变量, 我只知道对应着 sys.path:List[str] , 通常已经包含['Anaconda3/DLLs','Anaconda3/lib/site-packages'],还可以自己扩充.
当执行 python a/b/c.py 时, 会自动讲 源文件所在目录加入到 PYTHONPATH 中.
当项目中的一些 test, utils 脚本不在项目根目录下, 但也有执行需求时, 怎么办呢?

  • 源码中变更 PYTHONPATH
    import os, sys
    
    current_path = os.path.dirname(os.path.abspath(__file__))
    sys.path.insert(0, os.path.join(current_path, '../../'))
    
  • 启动命令中加入 PYTHONPATH (linux)
    将 PYTHONPATH=xx 和 python x.py 写在一行内. 见参考
    $ echo $PYTHONPATH
    
    $ python -c 'import sys;print("/tmp/pydir" in sys.path)'
    False
    $ PYTHONPATH=/tmp/pydir python -c 'import sys;print("/tmp/pydir" in sys.path)'
    True
    $ echo $PYTHONPATH
    

tips
避免与操作系统的 PATH 混淆,
它代表的是可执行文件的寻找目录, py中可通过 os.environ['PATH'] 读写.

参考

  1. s.o.f. add PYTHONPATH during command line module run

最后

以上就是尊敬刺猬为你收集整理的py “类,模块,包与库“ 的 import 机制概念明确import 导入机制PYTHONPATH参考的全部内容,希望文章能够帮你解决py “类,模块,包与库“ 的 import 机制概念明确import 导入机制PYTHONPATH参考所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部