博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python攻克之路-module
阅读量:5088 次
发布时间:2019-06-13

本文共 14421 字,大约阅读时间需要 48 分钟。

一、模块

例子:调用configpaser模块时,首先在当前的Python编译器去查找,找到后,里面没有ConfigParser()这个方法,直接报错,configparser应该让它去系统查找

import configparserconfig = configparser.ConfigParser()

在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。

为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就称之为一个模块(Module)。
使用模块有什么好处?
最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。但是也要注意,尽量不要与内置函数名字冲突。点这里查看Python的所有内置函数。
你也许还想到,如果不同的人编写的模块名相同怎么办?为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。
俗解:代码越写越多,可以使用分组来管理,如把时间相关的放入一个组,以后要调用时间就通过time模块都取,随机数相关的去random取,一层层的取,把功能分开

1、模块分为三种

- python标准库
- 第三方模块(非官方)
- 应用程序自定义模块(自定义py文件)

2、Python模块的调用

简单例子:[root@python3 module]# cat calculate.py #!/usr/local/python3/bin/python3def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3import calculate               ##调用print(calculate.add(1,2))[root@python3 module]# python3 bin.py 3

  

3、模块的搜索路径

[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3import sys                 ##调用sys模块查看import calculate print(calculate.add(1,2))print(sys.path)            ##sys.path方法[root@python3 module]# [root@python3 module]# python3 bin.py   #第一个路径就是当前的目录下module3['/root/py/fullstack_s2/week5/module', '/usr/local/python3/lib/python36.zip', '/usr/local/python3/lib/python3.6', '/usr/local/python3/lib/python3.6/lib-dynload', '/usr/local/python3/lib/python3.6/site-packages']

  

二、分析调用过程和方法

1.实际是Python解释器通过搜索路径把到calculate后,python解释器calculate所有代码都解释一次,无论是什么内容都可以通calculate去引用,调用函数中的add或sub或变量时,是通过calculate这个名字去调用方法

[root@python3 module]# cat calculate.py #!/usr/local/python3/bin/python3print('cal is ok')                   ##打印def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3import sysimport calculate                    ##只是调用[root@python3 module]# python3 bin.py cal is ok

变量的调用也是要通过calculate调用

[root@python3 module]# cat calculate.py #!/usr/local/python3/bin/python3print('cal is ok')x = 4                 ##def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3import sysimport calculate print(x)                        ###直接调用x[root@python3 module]# python3 bin.py cal is okTraceback (most recent call last):  File "bin.py", line 4, in 
print(x)NameError: name 'x' is not defined ##未定义[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3import sysimport calculate print(calculate.x) ##通过calculate的方法调用正常[root@python3 module]# python3 bin.py cal is ok4

import多个模块

import time,sys

  

2.从模块中调用某个方法(from module import func)

场景:模块文件里有很多函数,通过import相当于把所有的都加载一次,可以只调用某个函数来提高使用效率

[root@python3 module]# cat calculate.py #!/usr/local/python3/bin/python3print('cal is ok')x = 4def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import add             #从calculate中调用addprint(add(2,3))                       #直接使用函数[root@python3 module]# python3 bin.py cal is ok5[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import add,sub        ##同时调用多个print(add(2,3))print(sub(9,3))[root@python3 module]# python3 bin.py cal is ok56[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import add,sub        #通过from指定调用时,没有调用x,会报错,表示python并没加载xprint(add(2,3))print(sub(9,3))print(x)[root@python3 module]# python3 bin.py cal is ok56Traceback (most recent call last):  File "bin.py", line 5, in 
print(x)NameError: name 'x' is not defined ###[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import add,subprint(add(2,3))print(sub(9,3))print(calculate.x) ##通过calculate去调用,但是还是报错,calculate没被定义,证明只是加载了add,sub[root@python3 module]# python3 bin.py cal is ok56Traceback (most recent call last): File "bin.py", line 5, in
print(calculate.x)NameError: name 'calculate' is not defined ###

  

3.调用所有的方法,但是不使用模块名称去调用方法(from import *建议少用)

[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3 from calculate import *         #导入所有print(add(4,9))print(x)print(sub(3,9))[root@python3 module]# python3 bin.py cal is ok134-6

问题分析:from module import *存在的的问题,可能会有以下场景,calculate中有add函数,而调用的Py中也有同样的add函数,实际python解释器是从上到下执行,从from开始,导入模块就加载了def add,而本文件中也有一个def add,所以类似于在同一个Py上给一个变量进行先后赋值,后赋值的生效,*号是加载所有的函数,可能会造成调用的函数与同py中所写的函数的产生一个冲突

[root@python3 module]# cat calculate.py #!/usr/local/python3/bin/python3print('cal is ok')x = 4def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import *def add(x,y):    return x+y+9print(add(4,5))[root@python3 module]# python3 bin.py cal is ok18

类似同一个py加载一个函数

In [3]: def f():   ...:     print('f1')   ...:     In [4]: def f():   ...:     print('f2')   ...:     In [5]: f()f2

from module import *表示解释器把要加载都执行一次,即使调用多次

[root@python3 module]# cat calculate.py #!/usr/local/python3/bin/python3print('cal is ok')       ##print('cal2 is ok')      ##x = 4def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import *          #调用两次from calculate import *          #[root@python3 module]# python3 bin.py cal is ok                        #只执行一次cal2 is ok

  

4.别名的使用as

[root@python3 module]# cat bin.py #!/usr/local/python3/bin/python3from calculate import add as plusprint(plus(4,8))[root@python3 module]# python3 bin.py 12

  

三、包package

描述:模块为了组织函数,模块多了要组织模块,为了避免模块名的冲突,python引入了按目录来组织模块的方法

[root@python3 module]# tree web/web/                   #存放模块├── __init__.py         #区分是文件玩夹还是包├── logger.py└── main.py[root@python3 week5]# tree module/module/├── bin.py        #bin与web在同一层函数├── calculate.py└── web    ├── __init__.py    ├── logger.py    └── main.py

通过bin去调用web中的模块

[root@python3 week5]# cat module/web/logger.py#!/usr/local/python3/bin/python3def logger():    print('logging in logger')[root@python3 week5]# cat  module/bin.py #!/usr/local/python3/bin/python3from web import logger           ##from package import modulelogger.logger()[root@python3 week5]# python3 module/bin.pylogging in logger

两层目录的情况

[root@python3 week5]# mkdir module/web/web2[root@python3 week5]# touch module/web/web2/__init__.py[root@python3 week5]# mv module/web/logger.py module/web/web2/[root@python3 week5]# tree module/module/├── bin.py├── calculate.py└── web    ├── __init__.py    ├── main.py    ├── __pycache__    │   ├── __init__.cpython-36.pyc    │   └── logger.cpython-36.pyc    └── web2        ├── __init__.py        └── logger.py[root@python3 week5]# cat module/bin.py#!/usr/local/python3/bin/python3from web.web2 import logger                 ##使用点logger.logger()[root@python3 week5]# python3 module/bin.pylogging in logger

两层目录,再调用模块中的一个方法

[root@python3 week5]# cat module/bin.py#!/usr/local/python3/bin/python3from web.web2.logger import logger   ####logger()[root@python3 week5]# python3 module/bin.pylogging in logger

包调用的过程

[root@python3 week5]# cat module/web/__init__.pyprint('web init')[root@python3 week5]# cat module/bin.py #!/usr/local/python3/bin/python3import web                               #调用用包,实际是执行__init__.py的代码[root@python3 week5]# python3 module/bin.pyweb init

  

import模块与包的一个区别

模块调用:

[root@python3 week5]# cat module/calculate.py#!/usr/local/python3/bin/python3x=9                   #####def add(x,y):    return x+ydef sub(x,y):    return x-y[root@python3 week5]# cat module/bin.py #!/usr/local/python3/bin/python3import calculateprint(calculate.x)    #####[root@python3 week5]# python3 module/bin.py9

包调用:

[root@python3 week5]# cat module/web/main.py#!/usr/local/python3/bin/python3x=4              ###[root@python3 week5]# cat module/bin.py #!/usr/local/python3/bin/python3import web                    #import一个包,只是执行__init__与其他的模块没关系print(web.main.x)[root@python3 week5]# python3 module/bin.pyweb initTraceback (most recent call last):  File "module/bin.py", line 3, in 
print(web.main.x) #####不能以这种方式调用包中的模块中的一个变量AttributeError: module 'web' has no attribute 'main'[root@python3 week5]# cat module/bin.py#!/usr/local/python3/bin/python3from web import main ##正常的方式print(main.x)[root@python3 week5]# python3 module/bin.pyweb init4

  

四、BASEDIR的问题

1、目录结构

[root@python3 week5]# tree atm/atm/├── bin               #程序入口,程序有一个执行文件│   ├── bin.py│   └── __init__.py├── conf              #配置相关│   ├── __init__.py│   └── setting.py└── module            #与逻辑相关    ├── __init__.py    ├── logger.py    └── main.py模块之间调用:[root@python3 week5]# cat atm/module/logger.py #!/usr/local/python3/bin/python3def logging():    print('module logging')[root@python3 week5]# cat atm/module/main.py #!/usr/local/python3/bin/python3import logger          ####def main():    logger.logging()   ####main()[root@python3 week5]# python3 atm/module/main.pymodule logging

  

2、调用分析

a.logger模块是打印日志,被main模块后调用,可以调用成功,但是使用bin来调用时,可以找到main,但是由于bin和logger不在同一目录下,所以bin调用时打不到logger

[root@python3 atm]# cat module/logger.py #!/usr/local/python3/bin/python3def logging():    print('module logging')[root@python3 atm]# cat module/main.py #!/usr/local/python3/bin/python3import loggerdef main():    logger.logging()[root@python3 atm]# cat bin/bin.py #!/usr/local/python3/bin/python3from module import mainmain.main()[root@python3 bin]# python3 bin.py Traceback (most recent call last):  File "bin.py", line 2, in 
from module import mainModuleNotFoundError: No module named 'module' 找不到,但是在pycharm时,它会自动找追加路径到sys.path下,以避免了错误

  

b.要找到module就要实现自动追加脚本所有的目录路径

__file__:内部变量,取脚本名称

__file__:内部变量,取脚本名称[root@python3 bin]# cat bin.py #!/usr/local/python3/bin/python3print(__file__)[root@python3 bin]# python3 bin.py bin.py

path.abspath取绝对路径

[root@python3 bin]# cat bin.py #!/usr/local/python3/bin/python3import osprint(__file__)print(os.path.abspath(__file__))[root@python3 bin]# python3 bin.py bin.py/root/py/fullstack_s2/week5/atm/bin/bin.py

使用os.path.dirname取得atm的路径

[root@python3 bin]# cat bin.py #!/usr/local/python3/bin/python3import osprint(__file__)print(os.path.abspath(__file__))print(os.path.dirname(os.path.abspath(__file__)))print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))[root@python3 bin]# python3 bin.py bin.py/root/py/fullstack_s2/week5/atm/bin/bin.py/root/py/fullstack_s2/week5/atm/bin/root/py/fullstack_s2/week5/atm

使用sys.path.append追加到模块查找到目录

[root@python3 bin]# cat bin.py #!/usr/local/python3/bin/python3import os,sysBASIC_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))    ###sys.path.append(BASIC_DIR)                                               ###from module import mainmain.main()[root@python3 bin]# python3 bin.py   ##再执行成功                                     module logging

  

c.整个程序结构中所需要目录

假设项目为foo,建议有以下的目录结构[root@python3 day2]# tree foo/foo/├── bin│   └── foo├── docs│   ├── abc.rst│   └── conf.py├── foo│   ├── __init__.py│   ├── main.py│   └── test         │       ├── __init__.py│       └── test__main.py├── README├── requirements.txt└── setup.py

注释:

bin目录:存放项目的一些可执行文件,可以自定义为script/之类
foo目录:存放项目的所有源代码
  - 源代码的所有模块、包都应该放在此目录,不要置于顶层目录
  - 其子目录test/存放单元测试代码
  - 程序的入口最好命名为main.py
docs目录:存放一些文档
setup.py: 安装、部署、打包的脚本(写了一个软件,这个软件要有这的一个执行环境,可以通过这个命令安装好)
requirements.txt:存放软件依赖的外部Python包列表
README: 项目说明文件

README:简要描述该项目信息,让读者快速了解这个项目
说明事项:
  a.软件定位,软件的基本功能(开发语言的版本,如有些就使用Python2.7上运行)
  b.运行代码的方法,安装环境、启动命令等
  c.简要使用说明(如ftp有8个功能,那些已经实现,那些没实现要明说)
  d.代码目录结构说明,量多详细点可以说明软件的基本信息
  e.常见问题说明

 

requirements.txt和setup.py

setup.py
描述:使用setup.py来管理代码的打包、安装、部署问题.业界标准写法是用Python流行的打包工具setuptools来管理,
这种方式普遍用于开源项目中,不这这里的核心思想不是用标准化的工具来解决这些问题,而是说,一个项目一定
要有一个安装部署工具,能快速便捷的在一台新机器上将环境安装好、代码都部署好和将程序运行起来
注意事项:
  - 安装环境时经常忘记最近又添加一个新的python包,结果一到线运行,程序就会出错
  - Python包的版本依赖问题,有时程序中使用是一个版本的Python包,但是官方的已经是最新的包了,通过手动安装可能出错
  - 如果依赖包很多,一个个安装这些依赖很费时
  - 新手写项目时,将程序运行起来非常麻烦,因为可能经常忘记要怎么安装各种依赖
  所以setup.py可以将这些事情自动化起来,提高效率、减少出错的概率

 

requirements.txt

这个文件存在的目的是:
  - 方便开发者维护软件的包依赖,将开发过程中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包
  - 方便读者明确项使用了哪些Python包
这个文件的格式是每一行包含一个包依赖的说明,通常flask>=0.10这种格式,要求是这个格式能被pip识别,这样就可以
简单的通过pip install -r requirements.txt来把所有Python包依赖都装好了https://pip.pypa.io/en/stable/user_guide/

 

配置文件的使用方法

注意:在上面的目录结构中,没有将conf.py放在源代码目录下,而是放在docs/的目录下
很多项目对配置文件的使用是
  - 配置文件写在一个或多个python文件,如这里的conf.py
  - 项目中那个模块用到这个配置文件就直接通过import conf这种形式来做代码中使用配置
产生的问题
  - 让单元测试变得困难(因为模块内部依赖了外部配置)
  - 另一方面配置文件作为用户控制程序的接口,应当可以由用户自由指定该文件的路径
  - 程序组组件可复用性太差,因为这种惯穿所有模块的代码编码方式,使得大部分模块依赖conf.py这个文件
更好的配置方式
  - 模块的配置都是可以灵活配置的,不受外部配置文件的影响
  - 程序配置也是可以灵活控制的(如nginx,mysql的配置文件)
所以,不应当在代码中直接import conf来使用配置文件,上面目录结构的conf.py,是给出一个配置样例,不是在写死的程序中直接引用的配置文件,可以通过给main启动配置路径的方式来让程序读取配置内容,当然,这里的conf.py可以换个类似的名字,比如setting.py.或者可以使用其他格式的内容来编写配置文件,如setting.yaml之类的.

 

五、__name__变量

分析:if __name__=='__main__': 把程序写好,如何知道那些功能模块,配置等,一般模块之间是调用,本身是不希望调用的,当别人在调用时,会把测试代码也会被一起调用

[root@python3 day2]# cat name/foo.py #!/usr/local/python3/bin/python3def hi():    print('hi')hi()                                  #一般功能模块只用来调用,不需要执行,但是有时写完会做测试[root@python3 day2]# cat name/bin.py#!/usr/local/python3/bin/python3import foofoo.hi()[root@python3 day2]# python3 name/bin.pyhi                                   #import foo时会加载一次所有代码hi

解决方法:使用if __name__=='__main__'

[root@python3 day2]# cat name/foo.py#!/usr/local/python3/bin/python3def hi():    print('hi')if __name__=='__main__':    hi()                                   #可以作测试,而且在其他人使用时,测试的不会显示[root@python3 day2]# python3 name/foo.pyhi[root@python3 day2]# cat name/bin.py #!/usr/local/python3/bin/python3import foo#foo.hi()[root@python3 day2]# python3 name/bin.py

__name__的原理

[root@python3 day2]# cat name/foo.py #!/usr/local/python3/bin/python3def hi():    print('hi')print(__name__)[root@python3 day2]# python3 name/foo.py__main__                      #本身使用时是__main__[root@python3 day2]# cat name/bin.py #!/usr/local/python3/bin/python3import foo[root@python3 day2]# python3 name/bin.pyfoo

  

六、模拟实现一个ATM + 购物商场程序

- 额度15000或自定义
- 实现购物商场,买东西加入购物车,调用信用卡接口结账(要输入卡号和密码之类的)
- 可以提现,手续费5%
- 每月22号出账单,每月10号为还款日,过期未还,按欠款总额万分之5每日计息
- 支持多账户登录(多个用户都可以登录购物)
- 支持账户间转账(一个用户转到另一个用户,一个用户减,另一个用户就加上相应的款)
- 记录每月日常消费流水(在购物时加上)
- 提供还款接口
- atm记录操作日志(转账、还款之类的,是银行操作的)
- 提供管理接口,包括添加账户、用户额度、冻结账户等
- 用户认证用装饰器

 

转载于:https://www.cnblogs.com/reid21/articles/8949474.html

你可能感兴趣的文章
黑马程序员——2 注释
查看>>
用OGRE1.74搭建游戏框架(三)--加入人物控制和场景
查看>>
转化课-计算机基础及上网过程
查看>>
android dialog使用自定义布局 设置窗体大小位置
查看>>
ionic2+ 基础
查看>>
互联网模式下我们更加应该“专注”
查看>>
myeclipse集成jdk、tomcat8、maven、svn
查看>>
查询消除重复行
查看>>
Win 10 文件浏览器无法打开
查看>>
HDU 1212 Big Number(C++ 大数取模)(java 大数类运用)
查看>>
-bash: xx: command not found 在有yum源情况下处理
查看>>
[leetcode]Minimum Path Sum
查看>>
内存管理 浅析 内存管理/内存优化技巧
查看>>
hiho1079 线段树区间改动离散化
查看>>
【BZOJ 5222】[Lydsy2017省队十连测]怪题
查看>>
第二次作业
查看>>
【input】 失去焦点时 显示默认值 focus blur ★★★★★
查看>>
Java跟Javac,package与import
查看>>
day-12 python实现简单线性回归和多元线性回归算法
查看>>
Json格式的字符串转换为正常显示的日期格式
查看>>