Python项目中如何优雅的import

Python项目中如何优雅的import

前言

  • 以前有一篇关于Python编码规范的随笔, 可是写的比较杂乱, 由于提到了import语句, 在篇文章中, 我专门来说Python项目中如何更好的import

标准库与第三方库的导入

  • 导入一个模块, 若是模块名太长, 则使用import as; 若是是导入子模块, 则使用from import as
  • 若是须要导入类的, 则使用from import导入类, 若是要导入某一个模块的多各种的话, 则类名使用逗号分隔
  • 示例
    1. 导入sklearn中的svm中的SVC类
    import sklearn.svm
    from sklearn.svm import SVC
    1. 导入numpy中的random模块
    import numpy.random as nprand
  • 总结: 若是导入类的话, 必定是import somemod 和 from somemod import class两个语句组成的; 若是导入一个不一样的模块的则, 则通常就是import somemod

项目模块导入

  • 项目目录
wxoa ›› tree -Cl
.
├── main.py
├── test
└── wxoa
    ├── __init__.py
    ├── __pycache__
    │   └── __init__.cpython-35.pyc
    ├── entity
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-35.pyc
    │   │   └── user.cpython-35.pyc
    │   └── user.py
    └── util
        ├── __init__.py
        ├── __pycache__
        │   ├── __init__.cpython-35.pyc
        │   └── ioutil.cpython-35.pyc
        └── ioutil.py

7 directories, 12 files
  • 主程序为main.py, 项目名为wxoa, 存放源代码的目录也叫wxoa, 也是一个python package
  • 导入规则(在第一次写这篇文章的时候我喜欢相对导入(觉得google的sklearn是采用这种方式的, 可是在test中使用的是绝对导入(sklearn在test.py函数中直接使用绝对路径, 由于已经写好的sklearn已经安装到了python路径中了(sklearn的test是在这种状况下进行测试的), 而通常咱们的项目是没有安装到python路径中)), 可是官方建议绝对导入, 若是要使用绝对导入有不报错的话, 个人方法是这只软连接)
    • 存在python package(因此这里不包含main.py)中的python文件包导入的规则
      • 使用from . import somemod导入当前目录下的模块
      • 使用from ..somemod import submod导入上一级目录的somemod目录下的submod模块
      • 若是名称太长则使用as缩减
    • 不在python package(就是这里的main.py和test目录下的文件)中的python文件的导入规则
      • 使用from somemod.submod.subsubmod import some导入, 注意这里不使用.号起头, 关于使用., ..的做用在下面会说明, 若是使用了.起头则会报错, 提示父模块没有加载
      • 其中somemod就是咱们的源码的python package包名, 在这里就是wxoa
      • 若是名称太长则使用as缩减

关于.和..

  • 在包导入中, 若是出现了.和..起头, 则会涉及到package(不是module)的关系, ..表示上一级package, 这个上一级package须要有一个__init__.py才是合法的, .表示当前package, 当前package须要有一个__init__.py才是合法的java

  • .和..涉及到的python程序的启动项, 这里会比较复杂, 简而言之, 在涉及到..表示的上级package的时候, 若是python程序的启动文件就是在这里则Python解释器不会认为..表示的上级目录的package是一个合法的目录, 尽管有__init__.py文件, 所以会报错; 这样就给代码测试带来的麻烦, 不能直接在使用..和.中直接测试代码, 也就是
    if __name__ == '__main__': pass
    由于这样已启动程序就会报错, 因此报错, 在下面提出解决方案python

关于.和..带来的麻烦的解决方案

  • 和上面展现的项目目录同样, 主启动程序, 项目源代码(主要是模块), 测试代码分离, main.py在项目目录下, test(普通的文件夹, 存放python测试文件, 运行的时候cd ..目录, 也就是在醒目目录下, 使用python -m test.test1 执行程序)也在项目目录下, 项目源代码就是wxoa
  • 在main.py和test目录下的python文件中导入本身项目中的模块, 就不要使用.和..起头了, 不然会报错, 而是使用绝对路径, 如这里的, from wxoa.service import user

关于import

  • import在默认的状况下是查看__name__属性判断是否加载的, 若是这个模块是__main__则它就是top level(顶级)的, 没有上一级目录, 因此from .. import ....是会把报错的, 在python3中的添加了__package__来解决这个问题, 在执行有from ..import ...的文件的时候, 使用python -m pkg.modname 执行modname.py文件, 将__package__从None改成pkg.modname才能正确的运行程序, 当__package__生效的时候, __name__在导入模块的时候会被忽略

不建议使用全路径导入, 这样状况必须安装第三方库才能使用, 不然必定会出现import错误, 提示路径找不到

关于Python编程

  • 虽然Python是面向对象编程, 可是经过开源项目you-get发现, 能够将Python理解为面向模块开发, 模块在Python也是对象, 面向模块开发会让一切都轻松起来, 模块中定义的全局变量为其属性, 模块中的函数为其方法, 若是多个函数有联系, 再考虑将其封装到一个类中, 在调用该模块的时候, 通常经过一个模块函数返回对象, 不用让用户过多的考虑__init__()方法的参数, 直接在模块函数中配置好信息返回便可
  • 加入咱们开发一个util工具箱, 则创建一个util包(和Java的包同样), 在里面建立strings.py, log.py等模块(相似于Java中的一些.java文件), 在log.py模块文件中定义一些须要的函数, 函数之间有某种联系或者为了方便起见能够定义类封装

关于模块设计

  • 示例:
    • 建立一个工具包, 该包中有关于字符串和IO操做的内容
    1. 首先考虑都放在一个模块文件中, 文件他们都是工具, 放在util.py中是能够的
    2. 接着考虑到咱们不须要建立strings和io的类, 由于工具咱们只须要一个就能够, 这与模块是同样的特性, 因此将全部的操做写成函数, 若是这样的话, 模块中没有类对函数进行分类, 函数都在util.py中会很混乱, 因此将util.py升级为util包, 建立strings.py和io.py, 将对应的函数放入对应的模块文件中
  • 示例1:
    • 坦克游戏
    1. 考虑放到game.py模块下
    2. tank, bullet, wall等都是游戏中的对象, 而且他们与工具类不一样, 他们不仅是一个对象, 而是能够建立不少, 与模块特性不一样, 全部把他们都写成类, 在game文件中经过类划分是可行的方案
相关文章
相关标签/搜索