第十八篇 模块与包--time&random模块&模块导入import(os.path.dirname(os.path.abspath(__file__)))
模块
在Python中, 一个.py文件就称为一个模块。
使用模块的好处:
1. 最大的好处就是大大提高了代码的可维护性
2. 编写代码不必从零开始。一个模块编写完毕,就可以被其他地方引用。在写其他程序时,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
3. 使用模块还可以避免函数名与变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,在编写模块时,不必考虑名字会与其他模块冲突。但是,要注意尽量不要与内置函数名字冲突。
所以,模块一共有三种:
1. Python标准库
2. 第三方模块
3. 应用程序自定义模块
模块的导入
1. 使用import语句
# 两种不同的导入方式 # 多个模块分多行导入
import module1
import module2
... # 多个模块可以写在一行里导入
import module1, module2, module3, .....
当使用import语句的时候,Python解释器怎样找到对应的文件呢?
就是解释器有自己的搜索路径,存在sys.path里。
因此,若当前目录下存在要与要引入模块同名的文件,就会把要引入的模块屏蔽掉。
2. from... import....语句
from module import name1[, name2[,nameN]]
这个声明不会把整个modulename模块导入到当前的命名空间中,只会将它里面的name1 或者name2单个引入到执行这个声明的模块的全局符号表。
3. from ... import * 语句
from module import *
该语句提供了一个简单的方法来导入一个模块中的所有项目。
然而,这种方式并不推荐使用,因为可能存在引入的模块里某个变量名与自己定义的变量名相同,而导致执行错误。
4. 被导入模块与当前文件不在同一个目录
import sys
print(sys.path) # 放的路径,就是执行文件所在路径 cal文件里有个add功能
# 需求:传入个参数,可以执行add功能 # 跨文件引入的方式
# 1. 首先:要在main里引入cal
# 2. 其次:要在bin里引入main![]()
备注:
bin文件:一般是程序的入口
main文件:与逻辑相关的程序都放在main文件里
但是,通常情况下,bin都是写在包下面的,不会暴露在最外面。
记住下面的路径的写法,然后你的文件不管在哪个机器上使用都可以正常执行了。
看Day21 和 Day22(03-python-全栈三期-day22 BASEDIR的介绍 )
import sys
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
总的原理就是通过当前文件,一步步的往外找,找到你需要的文件目录,然后加入path 解析:
1. 首先要知道 __file__,就代表的是当前文件,此例子里就是bin.py文件
2. os.path.abspath(__file__):是__file__ 这个当前文件的绝对路径,找到bin目录
3. os.path.dirname(os.path.abspath(__file__)):就是通过2获取它的绝对路径的上一级绝对路径,到day21_lesson目录了
4. os.path.dirname(os.path.dirname(os.path.abspath(__file__))):再往上一层找,找到day21目录了 5. sys.path.append(BASE_DIR):把4找到的绝对路径加入到path里,之后,模块导入的时候,就会在day21目录下面找了 但是,也要知道,sys.path.append()也只是临时加入路径,不是永久加入的哦
5. 导入模块做的两件事
无论是上面1,2,3哪种导入方式,导入模块运行的本质都没有变,都做了2件事: 1. 首先通过sys.path找到被导入的模块(.py文件)
2. 然后执行全部被导入的模块。 区别是:
import module 会将module这个变量名加载到名字空间
from module import name 只会将 name这个变量名加载进
模块的动态导入
上面介绍了模块的正常导入,但是如果给的是一个字符串,那怎么导入呢?目录结构如下:
需求是:要将m1下的t.py导入到01.动态导入模块.py文件里
# 1. 正常的导入及调用执行
from m1 import t
t.test1()
# 2. 现在有个新问题,要求你不能按照上面的方式到导入,给的是个字符串 'm1.t'
# 通过字符串方式导入模块
module_t = __import__('m1.t')
print(module_t)
# <module 'm1' (namespace)>
# 为什么导入的模块是m1,而不是t呢?而我们要导入的就是t模块啊?
'''
这种导入方式,不管你下面套多少层,返回的都是最顶层的模块
'''
# 调用:都需要通过最顶层的模块以.的方式,一层一层的往下找,直到调用你需要引用的模块
module_t.t.test1()
# 3. 利用importlib模块导入字符串形式的模块
import importlib
m = importlib.import_module("m1.t")
print(m)
# <module 'm1.t' from 'F:\\workspace\\Try2\\m1\\t.py'>
# 以这种方式导入,直接就定位到你想要调用的t模块了 # 调用
m.test1()
总结:
__import__(‘m1.t') 与 import.importLib(’m1.t') 导入的都是 字符串'm1.t'模块,为啥定位的模块不一样呢?也就是两者的区别?
1. __import__(‘m1.t') :是python内部的调用方式,它只能定位到最顶层的模块,调用的时候需要以点的方式,一级级往下找,直到找到你需要的模块
2.importLib('m1.5'):是面向用户的模块导入方式,它能直接定位到你需要导入的模块,所以,如果传入的是字符串形式的模块名,推荐用这种方式导入。
包
可以将不同类型、功能的文件放到不同的包里,方便管理
引用包
# 引用包有两种方式,包与包之间通过.号连接
在图中 module-lesson.py里执行cal.py文件 # 第一种:导入模块
from web.web1.web2 import cal cal.add(3,4) # 第二种:把模块和包写在一起,导入方法
from web.web1.22.cal import add add(3,5)
__name__:
# 1. 在执行文件里(当前正在被执行的文件就是执行文件) print(__name__)
#结果
__main__ # 2. 在调用文件里执行
A文件里导入了B模块,A文件就是调用文件,B模块文件是被调用文件
print(__name__)
# 结果
是B模块的文件名 (Pycharm会自作主张给出文件路径) 知道了这个原理,那if __name__=="__main__" 有什么作用呢? # 1. 如果放在被调用文件里,用于被调用文件的测试
if __name__=="__main__":
print("ok")
a=add(5,8)
print(a) 解释:
一般写好了一个被调用文件,肯定是要先进行测试的,测试通过了,才能让别人调用。那么测试一般也是在被调用文件里进行的:
如果不加if __name__=="__main__",那么,该文件被调用后,测试代码就会被执行;
如果加上了if __name__=="__main__",Python就会知道该语句下面的代码是测试代码,其他人引入该文件,就自动忽略了(忽略了这写测试代码,不会被执行),而不去执行了。 # 2. if __name__=="__main__"如果放到执行文件里,就一点,意思是这个执行文件不想被其他人调用。(就是禁止别人调用我的文件)。 比如bin.py一般作为程序的入口,不希望别人调用,那也可以加上
if __name__=="__main__": 所以,写代码要养成习惯,在文件里要加上 if __name__=="__main__", 主动避免一些坑。
Python内置模块
1. time模块
文件名与内置模块同名,是可以的。
time模块里需要掌握的三种时间表达式。
关于时间模块,记住两张图
# 1. 时间戳:是一堆秒数
# 作用:做计算来用的
print(time.time())
#1481321748.481654秒 1970.1.1 00:00:00开始计算到当前为止总归的秒数
# 1970年是unix诞生的日子 # 2. #结构化时间---当地时间 print(time.localtime()) # 结果
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=26, tm_hour=13, tm_min=7, tm_sec=29, tm_wday=1, tm_yday=177, tm_isdst=0) # tm_wday :表示这个星期的第几天,默认是从0开始的,1代表星期二
# tm_yday: 表示当前是第多少天 print(time.localtime(1529989999.4332166))
# 结果
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=26, tm_hour=13, tm_min=13, tm_sec=19, tm_wday=1, tm_yday=177, tm_isdst=0) t=time.localtime()
print(t.tm_year) #
print(t.tm_wday) # 1 # 星期二,做显示的时候,需要手动 +1,转换为人类意识能接受的之后再显示 #-----#结构化时间---UTC市区,世界标准时间
print(time.gmtime()) # 结果
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=26, tm_hour=5, tm_min=15, tm_sec=47, tm_wday=1, tm_yday=177, tm_isdst=0) print(time.gmtime(time.time()))
# 结果
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=26, tm_hour=5, tm_min=22, tm_sec=51, tm_wday=1, tm_yday=177, tm_isdst=0) # 将结构化时间转换成时间戳
print(time.mktime(time.localtime()))
# 1529990485.0 # 将结构化时间转换成字符串时间(******) strftime()
# 第一个参数:转换后的显示格式
# 第二个参数:要转换的时间
print(time.strftime("%Y---%m-%d %X",time.localtime()))
# 结果
2018---06-26 13:25:27
# 年: %Y 月:%m 日:%d 时分秒:%X
# 年月日之间的分隔符完全是自己定义的 # 将字符串时间转换为结构化时间 strptime()
# 第一个参数:字符串时间,要转换的时间
# 第二个参数:结构化时间的格式与第一个字符串时间进行对应
print(time.strptime("2016:12:24:17:50:36","%Y:%m:%d:%X")) # 重点记住下面两种转换,因为不需要自己再自定义时间格式了
asctime()
# 把一个表示时间的元组或者结构化时间 表示为:Tue Jun 26 13:35:21 2018 这种固定的形式
# 如果没有传参数,会默认将time.localtime()作为参数传入
print(time.asctime(time.localtime())) # Tue Jun 26 13:35:21 2018 ctime()
# 把一个时间戳(按秒计算的浮点数)转换为time.asctime()的形式。
# 如果参数未给或者为None的时候,会默认将time.time()作为参数。
# 他的作用相当于time.asctime(time.localtime())
print(time.ctime()) # Tue Jun 26 13:36:26 2018
2. datetime 模块
import datetime
print(datetime.datetime.now())
# 结果
2018-06-26 13:43:04.853231
3. random 模块
random模块提供各种用于生产伪随机数的函数,以及根据不同的实数分布来随机生产值的函数。
# random() :
生成(0,1)内的随机浮点数
ret = random.random() # uniform(a,b):
生成[a,b) 内的大于1的随机浮点数
ret=random.uniform(1,4) # randint(a,b) :
生成[a,b]内的随机整型数字,闭区间
ret=random.randint(1,3) # randrange(a,b [,step]) :
生成[a,b)内的随机整型数字,左闭右开区间, step表示步长
ret=random.randrange(1,10,2) # 只能在 1,3,5,7, 9里随机生成 随机序列:
# choice(seq):
从非空序列seq中返回一个随机元素
ret=random.choice([11,22,33,44,55]) # sample(seq, len) :
返回长度为len的序列,包含从序列 seq中随机选择的元素。结果序列中的元素按照选择他们时的顺序排列
ret=random.sample([11,22,33,44,55],3) # shuffle(x, [random]):
随机原地打乱列表x中的项,random是可选参数,它指定随机生成函数。如果提供该参数,则该参数不能是包含参数并且返回范围在[0.0, 1.0)内的浮点数的函数。
ret=[1,2,3,4,5]
random.shuffle(ret)
print(ret) # [2, 1, 5, 4, 3]-->随机乱序的
生成一个数字和字母并存的4位数的随机验证码
def vCode():
ret = ""
for i in range(4):
num = random.randint(0,9)
alf = chr(random.randint(65,122)) # A~Z 和 a~z
finalVocd = str(random.choice([num, alf]))
ret += finalVocd # 字符串拼接
return ret print(vCode())
第十八篇 模块与包--time&random模块&模块导入import(os.path.dirname(os.path.abspath(__file__)))的更多相关文章
- python成长之路【第十八篇】:python模块介绍、模块导入和重载
一.模块和命名空间 一般来说,Python程序往往由多个模块文件构成,通过import语句连接在一起.每个模块文件是一个独立完备的变量包,即一个命名空间.一个模块文件不能看到其他文件定义的变量名,除非 ...
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
- Egret入门学习日记 --- 第十八篇(书中 8.5~8.7 节 内容)
第十八篇(书中 8.5~8.7 节 内容) 其实语法篇,我感觉没必要写录入到日记里. 我也犹豫了好久,到底要不要录入. 这样,我先读一遍语法篇的所有内容,我觉得值得留下的,我就录入日记里. 不然像昨天 ...
- python基础知识-day8(模块与包、random、os)
1.模块与包 package:相同的模块代码存储在一个目录下(即包里边会包含多个模块). 包不能存储在文件夹的目录下,模块名称不能使用关键字.(不包含工程文件夹) 2.模块与包的实例 1)在工程文 ...
- Python之路(第十八篇)shutil 模块、zipfile模块、configparser模块
一.shutil 模块 1.shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中,需要打开文件 import shutil shutil.co ...
- Android UI开发第二十八篇——Fragment中使用左右滑动菜单
Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...
- 跟我学SpringCloud | 第十八篇:微服务 Docker 化之基础环境
1. 容器化 Docker 的横空出世,给了容器技术带来了质的飞跃,Docker 标准化了服务的基础设施,统一了应用的打包分发,部署以及操作系统相关类库等,解决了测试生产部署时环境差异的问题.对于运维 ...
- python学习之【第十六篇】:Python中的常用模块之OS模块、sys模块、random模块
1. OS模块 OS模块是与操作系统交互的一个接口.内部提供了以下方法: os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname& ...
- python 中 模块,包, 与常用模块
一 模块 模块:就是一组功能的集合体, 我们的程序可以直接导入模块来复用模块里的功能 导入方式 一般为 : import 模块名 在python中, 模块一般分为四个通用类别 1使用python编写. ...
随机推荐
- bootstrapPaginator设置同步会翻2页的小坑
因为需要用到post的返回值在做后面的决定.不想嵌套在回调函数中.网上找了一下.设置为同步 $.ajaxSetup( { async: false }); 结果bootstrap的翻页组件就出了bug ...
- PHP中级面试经历
资源来自网络:http://www.2cto.com/kf/201304/204749.html 1.用PHP打印出前一天的时间格式是2006-5-10 22:21:21(2分) 2.echo(),p ...
- Python—面向对象 封装03
接着上面的一篇继续往下: 如何隐藏 在python中用双下划线开头的方式将属性隐藏起来(设置成私有的) class A: __x = 1 # _A__x = 1 def __init__(self, ...
- HTML5笔记——第一节
我的第一个网页 <!--html的基础模板--><!--html hyperText markup Language--><!--声明文档类型--><!DOC ...
- 有连接服务&无连接服务
面向连接的服务 通信双方在通信时要事先建立一条通信线路,其过程包括建立连接.使用链接.释放链接三个过程 如: TCP 电话 面向无连接的服务 通信双方不需要事先建立一条通信线路,而是把每个带有目的选址 ...
- atan和atan2反正切计算
typedef struct point { double x, y; }point; //给定两个点 point a(x1,y1),b(x2,y2); 使用反三角函数atan求斜率,原型如下 flo ...
- ABAP术语-Function Builder
Function Builder 原文:http://www.cnblogs.com/qiangsheng/archive/2008/02/03/1063196.html Tool for creat ...
- 使用SimpleDateFormat解析日期得到年份不正确的结果
今天写项目的时候发现日期解析结果不对,很纳闷,从控制台中看传过来的数据是对的,但解析得到数据就是错的,如下图 最终查资料发现是格式上的错误,年份的YYYY应该改成yyyy,之后就正常了. 以下是正确格 ...
- JDK8 新特性
JDK8 新特性目录导航: Lambda 表达式 函数式接口 方法引用.构造器引用和数组引用 接口支持默认方法和静态方法 Stream API 增强类型推断 新的日期时间 API Optional 类 ...
- Mina 组件介绍之 IoBuffer
在Java NIO 中,ByteBuffer通常作为通信中传递消息的载体.而在Mina中,采用了IoBuffer代替ByteBuffer.Mina给出了不用ByteBuffer的两个主要理由: 1. ...