python学习笔记五 模块上(基础篇)

模块学习

模块,用一砣代码实现了某个功能的代码集合。 

类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块。

模块分为三种:

  • 自定义模块
  • 内置标准模块(又称标准库)
  • 开源模块

自定义模块:

#hello.py
def hello():
    print("hello world")

if __name__ == "__main__":
    hello()


import hello
hello.hello()

模块导入

Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入。导入模块有一下几种方法:

1 import module
2 from module.xx.xx import xx
3 from module.xx.xx import xx as rename  
4 from module.xx.xx import *

导入模块其实就是告诉Python解释器去解释那个py文件

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 __init__.py 文件

那么问题来了,导入模块时是根据那个路径作为基准来进行的呢?即:sys.path

import sys,pprint
pprint.pprint(sys.path)
['C:\\Users\\Administrator\\PycharmProjects\\S12\\test',
 'C:\\Users\\Administrator\\PycharmProjects\\S12',
 'C:\\Windows\\system32\\python34.zip',
 'C:\\Python34\\DLLs',
 'C:\\Python34\\lib',
 'C:\\Python34',
 'C:\\Python34\\lib\\site-packages']

自定义模块存放位置

可以修改python环境变量:

Unix 系统设置.bashrc

export PYTHONPATH=$PYTHONPATH:~/python

window中编辑autoexec.bat文件(在C盘的根目录下)增加一行配置:

set PYTHONPATH=%PYTHONPATH%;C:\python

还可以添加sys.path

base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

sys.path.append(base_dir)

模块间相互调用

目录结构:
dj
├── backend
│   ├── db
│   │   ├── __init__.py
│   │   └── sql_api.py
│   ├── __init__.py
│   └── logic
│       ├── handle.py
│       └── __init__.py
├── config
│   ├── __init__.py
│   └── settings.py
├── frontend
│   └── __init__.py
├── __init__.py
└── user_main.py

#user_main.py
import sys,os
from backend.logic import handle
handle.home()  #程序入口

#handle.py
import sys,os
from backend.db.sql_api import select

def home():
    print("welcome to home page")
    q_data = select("user",'haha')
    print("query res:",q_data)

def movie():
    print("welcome to movie page")

def tv():
    print("welcome to tv page")

#sql_api.py
import sys,os
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #定位至dj目录,添加至sys.path
sys.path.append(base_dir)
from config import settings 

def db_auth(configs):
    if configs.DATABASE['user'] == "root" and configs.DATABASE['password'] == "123":
        print("db authentication passed")
        return True
    else:
        print("db error...")

def select(table,column):
    if db_auth(settings):
        if table == 'user':
            user_info = {
                "001":["a1",18,'engineer'],
                "002":["a2",28,'chef'],
                "003":["a3",38,'protect']
            }
            return user_info

#settings.py
DATABASE = {
    'user':'root',
    'password':'123',
    'port':3306,
    'host':'localhost',
    'engine':'mysql'
}

模块调用顺序

一、os模块

print(os.getcwd()) #获取当前工作目录,即当前python脚本工作的目录路径
os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #改变当前脚本工作目录;相当于shell下cd
os.curdir #返回当前目录: (
'.')
os.pardir #获取当前目录的父目录字符串名:(
'..')
os.makedirs(
'dirname1/dirname2') #可生成多层递归目录
os.removedirs(
'dirname1') #若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir(
'dirname') #生成单级目录;相当于shell中mkdir dirname
os.rmdir(
'dirname') #删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir(
'dirname') #列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() #删除一个文件
os.rename(
"oldname","newname") #重命名文件/目录
os.stat(__file__) #获取文件
/目录信息
os.stat(path)执行一个stat()系统调用在给定的path上,返回一个类元组对象(stat_result对象,包含10个元素),属性与stat结构成员相关:st_mode(权限模式),
st_ino(inode number),st_dev(device),st_nlink(number of hard links),st_uid(所有用户的user id),st_gid(所有用户的group id),st_size(文件大小,以位为单位),
st_atime(最近访问的时间),st_mtime(最近修改的时间),st_ctime(创建的时间)

os.path.getatime(__file__) #返回path所指向的文件或者目录的最后存取时间

os.path.getmtime(__file__) #返回path所指向的文件或者目录的最后修改时间

os.sep #输出操作系统特定的路径分隔符,win下为
"\\",Linux下为"/"
os.linesep #输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep #输出用于分割文件路径的字符串
os.name #输出字符串指示当前使用平台。win
->'nt'; Linux->'posix'
os.system("dir") #运行shell命令,直接显示
os.environ #获取系统环境变量
os.path.abspath(__file__) #返回path规范化的绝对路径
os.path.split(__file__) #将path分割成目录和文件名二元组返回
os.path.dirname(__file__) #返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(__file__) #返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(__file__) #如果path存在,返回True;如果path不存在,返回False
os.path.isabs(__file__) #如果path是绝对路径,返回True
os.path.isfile(__file__) #如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(__file__) #如果path是一个存在的目录,则返回True。否则返回False
#os.path.join(__file__[, path2[, ...]]) #将目录与文件重新组合 atm_user_file_path
= os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), r'atm\db\user.db')

二、sys模块

sys.argv           #命令行参数List,第一个元素是程序本身路径

sys.exit(
"bye") #退出程序,正常退出时exit(0)
sys.version #获取Python解释程序的版本信息
sys.maxint #最大的Int值
sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform #返回操作系统平台名称
sys.stdout.write(
'please:')

#模拟进度条功能
for i in range(1,10):
sys.stdout.write('#')
sys.stdout.flush()
time.sleep(0.5)

val
= sys.stdin.readline()[:-1]

三、random模块

li = [23,52,12,4,7,18,33,99,25]
print(random.random()) #随机小数
0.16377927048277297
print(random.uniform(1,10)) #返回随机实数n 其中1<=n<10
2.5185093102244163
print(random.randint(1,3)) #随机1-3
3
print(random.randrange(1,10)) #返回range(start,stop,step)中的随机数
9
print(random.choice(li)) #从序列seq中返回随机元素
52
random.shuffle(li) #原地指定序列seq
print(li)
[99, 12, 4, 52, 23, 18, 33, 7, 25]
print(random.sample(li,5))
[33, 25, 99, 52, 12]

#生成验证码
checkcode = ''
for i in range(4):
    current = random.randrange(0,4)
    if current != i:
        temp = chr(random.randint(65,90))
    else:
        temp = random.randint(0,9)
    checkcode += str(temp)
print(checkcode)

四、time模块

时间相关的操作,时间有三种表示方式:

  • 时间戳               1970年1月1日之后的秒,即:time.time()
  • 格式化的字符串    2014-11-11 11:11,    即:time.strftime('%Y-%m-%d')
  • 结构化时间          元组包含了:年、日、星期等... time.struct_time    即:time.localtime()

三种方式间的转换

python学习笔记五 模块上(基础篇)

import time,datetime

#time.sleep(3)

print(time.clock()) ##返回处理器时间

print(time.time()) #返回当前系统时间戳

print(time.ctime()) #输出Tue Jan 26 18:23:48 2016 ,当前系统时间,返回字符串格式

print(time.ctime(time.time()-86400)) #将时间戳转为字符串格式,可以同时间戳运算

print(time.gmtime(time.time()-86400)) #将时间戳转换成struct_time格式,格林乔治时间

print(time.localtime(time.time()-86400)) ##将时间戳转换成struct_time格式,当前时间

print(time.asctime()) #将struct_time格式转成字符串格式

print(time.mktime(time.localtime())) #将struct_time格式转回成时间戳

print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())) #将struct_time格式转成指定的字符串格式

print(time.strptime("2016-01-28","%Y-%m-%d")) #将字符串格式转换成struct_time格式

print(datetime.date.today()) #输出格式 2016-01-26

print(datetime.date.fromtimestamp(time.time()-864400)) #2016-01-16 将时间戳转成日期格式

current_time = datetime.datetime.now() #输出当前时间

print(current_time) #输出2016-01-26 19:04:30.335935

#timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
print(datetime.datetime.now() - datetime.timedelta(days=5))

print(current_time.timetuple()) #返回struct_time格式

#datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])
print(current_time.replace(2014,9,12)) #输出2014-09-12 19:06:24.074900,返回当前时间,但指定的值将被替换

str_to_date = datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") #将字符串转换成日期格式
print(str_to_date)

new_date1 = datetime.datetime.now() + datetime.timedelta(days=10) #比现在加10天
new_date2 = datetime.datetime.now() + datetime.timedelta(days=-10) #比现在减10天
new_date3 = datetime.datetime.now() + datetime.timedelta(hours=-10) #比现在减10小时
new_date4 = datetime.datetime.now() + datetime.timedelta(minutes=120) #比现在+120s
print(new_date1)
print(new_date2)
print(new_date3)
print(new_date4)

python学习笔记五 模块上(基础篇)

Arrow: better dates and times for Python

推荐一个不错的时间和日期处理模块。。。

http://arrow.readthedocs.io/en/latest/

re模块

匹配格式:

模式

描述

^

匹配字符串的开头

$

匹配字符串的末尾。

.

匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。

[...]

用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k',所有特殊字符在字符集中都将失去原有的特殊含义,在字符集中如果要使用[,],^,-,可以在前面加上反斜杠。

[^...]

不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

*

匹配0个或多个的表达式。

+

匹配1个或多个的表达式。

?

匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

{n}

精确匹配n前面表达式。

{n,}

精确匹配至少n个前面表达式。

{n,m}

匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式

a|b

匹配a或b

(...)

匹配括号内的表达式,也表示一个组,从表达式左边开始每遇到一个分组的左括号'(',编号+1,分组表达式作为一个整体,后面可以接数量词。表达式中的|仅在该组中有效。

(?imx)

正则表达式包含三种可选标志:i,m,或x。只影响括号中的区域。

(?-imx)

正则表达式关闭i,m,或x可选标志。只影响括号中的区域。

(?:...)

类似 (...), 但是不表示一个组用于使用“|”或后接数量词

(?imx:re)

在括号中使用i,m或x可选标志

(?-imx:re)

在括号中不使用i,m或x可选标志

(?#...)

#后的内容将被作为注释被忽略。

(?<=...)

后向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的左边。

(?=...)

前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。

(?!...)

前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功

(?>...)

匹配的独立模式,省去回溯。

\w

匹配字母数字[a-zA-Z0-9]

\W

匹配非字母数字[^A-Za-z0-9_]

\s

匹配任意空白字符,等价于[\t\n\r\f].

\S

匹配任意非空字符[^ \f\n\r\t\v]

\d

匹配任意数字,等价于[0-9].

\D

匹配任意非数字

\A

匹配字符串开始

\Z

匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。

\z

匹配字符串结束

\G

匹配最后匹配完成的位置。

\b

匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B

匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

\n,\t,等.

匹配一个换行符。匹配一个制表符等

\1...\9

匹配第n个分组的子表达式。

\10

匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符

码的表达式。

 
更多匹配格式:
python学习笔记五 模块上(基础篇)
re模块重要的函数:
 
compile(pattern[,flags])                  根据包含正则表达式的字符串创建模式对象
search(pattern,string[,flags])          根据模式去字符串中匹配指定内容,匹配第一个
match(pattern,string[,flags])          在字符串的开始处匹配模式
split(pattern,string[,maxsplit=0])    根据模式的匹配项来分隔字符串
findall(pattern,sting)                      列出字符串中模式的所有匹配项
sub(pat,repl,string[,count=0])        将字符串中所有pat的匹配项用repl替换
escape(string)                                 将字符串中所有特殊正则表达式字符转义
 
正则表达式实例
pattern = re.compile(r'hello')       #创建一个'hello'的模式对象,compile也有search或者match函数
match = pattern.match('hello world')  #只能匹配字符串开头

pattern = re.search('\d+','whar are you 2b?')
if pattern:
     print(pattern.group())

pattern = re.compile(r'\d+')
print(pattern.split('one1two2three3four4',maxsplit=4))  #最大分割次数
['one', 'two', 'three', 'four', '']

print(pattern.findall('one1two2three3four4'))
['1', '2', '3', '4']

print(re.sub('\s*','','a b c d'))
'abcd'

#选择符和子模式:(|) 匹配改分组中左右表达式的任意一个
 
s = 'python or perl'
print(re.search('p(ython|erl)',s).group())
#可选项和重复子模式

r(http://)?(www\.)?python\.org

#匹配如下:
'http://www.python.org'
'http://python.org'
'www.python,org'
'python,org'
 
#分组
 
a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group())
123abc456
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))
123abc456
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))
123
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))
abc
print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups())
('123', 'abc', '456')
 
取email地址: 
name = '[email protected] http://gmail.com'
pat = re.compile(r'[a-zA-Z0-9_.][email protected][a-zA-Z0-9.]+')
print(pat.search(name).group())

手机号:
^1[3|4|5|8][0-9]\d{8}$

pickle 和 json模块

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

import json

info = {'name':'koka','age':23} #json只能处理简单的字典和python数据类型

f = open('test.txt','w') 
json.dump(info,f)
f.close()


f = open('test.txt','r')
account_info = json.load(f)
f.close()
print(account_info)

-------------
info = {
'1001':'haha','money':1200,
}
data = json.dumps(info)
f = open('log.txt','w')
f.write(data)
f.close()

f = open('log.txt','r')
account_info = json.loads(f.read())
print(account_info)

pickle模块提供了四个功能:dumps、dump、loads、load

import pickle

info = { '1001':{'haha','123',1200,1200}, '1002':{'hehe','123',1500,1500}, '1003':{'heihei','123',1800,1800}, '1004':{'hoho','123',2100,2100} } f = open('test.txt','wb') pickle.dump(info,f) f.close() f = open('test.txt','rb') account_info = pickle.load(f) f.close() print(account_info)

----------------
info = {
'1001':'haha','money':1200,
}
data = pickle.dumps(info)
f = open('log.txt','wb')
f.write(data)
f.close()

f = open('log.txt','rb')
account_info = pickle.loads(f.read())
print(account_info)