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才是合法的

  • .和..涉及到的python程序的启动项, 这里会比较复杂, 简而言之, 在涉及到..表示的上级package的时候, 如果python程序的启动文件就是在这里则Python解释器不会认为..表示的上级目录的package是一个合法的目录, 尽管有__init__.py文件, 因此会报错; 这样就给代码测试带来的麻烦, 不能直接在使用..和.中直接测试代码, 也就是

    if __name__ == '__main__':
    pass

因为这样已启动程序就会报错, 所以报错, 在下面提出解决方案

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

  • 和上面展示的项目目录一样, 主启动程序, 项目源代码(主要是模块), 测试代码分离, 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文件中通过类划分是可行的方案

Python项目中如何优雅的import的更多相关文章

  1. 在 python 项目中如何记录日志

    一. 概述 写本文的目的是我在写 python 项目的时候需要记录日志,我忘记怎么处理了,每次都需要去网上查一遍,好记性不如烂笔头, 这里把查阅的内容记录下来,方便以后查找. python 项目中记录 ...

  2. python项目中requirements的巧用(一键导入所有安装包)

    一个Python 项目中可能安装很多安装包, 再次创建虚拟环境是需要重新安装的话很麻烦也费时间, 或者项目部署的时候避免重装, 可以将现有项目的所有安装包记录在requirements.txt 文件, ...

  3. 在eclipse中,Python项目遇到:…… from appium import webdriver ImportError: No module named appium

    1) Traceback (most recent call last):   File "D:\python workspace\src\p_test01\__init__.py" ...

  4. python 项目中包中__init__.py文件的作用

    开发python项目时,我遇到了一个这样的现象,当我新建一个pythonpackage时,总会自动地生成一个空的__init__.py文件,因为是python新手,所以很不了解这个空文件的作用是什么, ...

  5. Python项目中的单元测试

    引入 单元测试负责对最小的软件设计单元(模块)进行验证,unittest是Python自带的单元测试框架. 单元测试与功能测试都是日常开发中必不可少的部分,本文演示了Python中unittest单元 ...

  6. [git]安装git-pylint-commit-hook提高python项目中的代码质量

    什么是'git-pylint-commit-hook' 我在工作中,团队为了保证代码和提高代码的质量,要求每个项目都要求安装git-pylint-commit-hook,它是个钩子,会在你提交代码到本 ...

  7. 生成指定python项目中所有的依赖文件

    一. pipreqs工具 这个工具的好处是可以通过对项目目录的扫描,自动发现使用了那些类库,自动生成依赖清单. 缺点是可能会有些偏差,需要检查并自己调整下. 安装: pip install pipre ...

  8. python中如何优雅使用import

    http://note.youdao.com/noteshare?id=c55be6a8565f5eb586aa52244b3af010

  9. python 项目中的 requirements.txt

    背景 java项目的话,包依赖一般都是maven管理,当然还有gradle,对于包的管理非常方便,maven的话只要在pom.xml中添加依赖包的maven坐标就可以了的,那python呢 ? 解决方 ...

随机推荐

  1. 死磕Java之聊聊HashSet源码(基于JDK1.8)

    HashSet的UML图 HashSet的成员变量及其含义 public class HashSet<E> extends AbstractSet<E> implements ...

  2. vue生态圈

    本文来自网易云社区 作者:刘凌阳 前言 公司社区上关于Vue的文章挺少的(少的可怜),不禁为Vue愤愤不平,此文应运而生. 但笔者水平有限,也写不了什么特别高深的东西,只能简单介绍下Vue生态圈,如有 ...

  3. poi将图片导入excel(Java代码)

    package com.fh.util;import java.awt.image.BufferedImage;  import java.io.ByteArrayOutputStream;  imp ...

  4. loj #2538. 「PKUWC2018」Slay the Spire

    $ \color{#0066ff}{ 题目描述 }$ 九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\) ...

  5. SQL SERVER下有序GUID和无序GUID作为主键&聚集索引的性能表现

     背景 前段时间学习<Microsoft SQL Server 2008技术内幕:T-SQL查询>时,看到里面关于无序GUID作为主键与聚集索引的建议,无序GUID作为主键以及作为聚集索引 ...

  6. mysql 面试题

    1.一张表,里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把Mysql重启,再insert一条记录,这条记录的ID是18还是15 ?   2.Mysql的技术特 ...

  7. Python之freshman07 面向对象编程jinjie

    本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程 经典类vs新式类 把下面代码 ...

  8. N1 Armbian 安装 OpenMediaVault

    前言 接上一篇继续折腾,这次在 N1 上进行一些本地化设置并安装使用 OpenMediaVault 步骤 使用 ssh 连接到 N1,修改系统源 cd /etc/apt cp sources.list ...

  9. vim多行注释与删除

    一.多行注释 1. 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式;2. 在行首使用上下键选择需要注释的多行;3. 按下键盘(大写)“I”键,进入插入模式:4. 然后输入注 ...

  10. rest-assured之获取响应数据(Getting Response Data)

    我们使用rest-assured可以获得响应内容,比如:我们发起一个get请求 get("/lotto") 并且获得响应内容,我们有多种方式可以实现: // 通过流的方式获得响应内 ...