2.python基础之内置模块认识
一、time模块
(1)概念:系统函数与一些模块就是python写好的 (2)调用模块 import time 查看time有哪些功能,用help函数查 print(help(time)):提供了操作时间值的内容,时间有三种表达方式 1.模块的内置方法 print(time.time())---打印当前时间戳 print(time.clock())---6.9e-07()6.9*10的负7次方,表CPU执行的时间 print(time.sleep(3))---本身cup执行很短,但与内存等了3s print(time.gmtime())---时区,东边国家先见太阳,地球划24个时区,一个时区1个小时,北京是东8区,英国是UTC时间中心时间,中国是CST时间 这个打印的是当前UTC时间,年月日 print(time.localtime())---当前中国时区的时间,本地时间,年月日(tm_year=2016,tm_mon=9...) print(time.strftime(format,p_tuple))---struct=time.localtime print(time.strftime('%Y-%m-%d %H:%M:%S',struct)) print(time.strptime(string,format))--2020-11-13 00:00:00 %Y-%m-%d %H:%M:%S----结果是tm_year=2016,tm_mon=9...就变为元组了,这时就可以赋给变量取里面的值了 print(time.ctime())--当前时间,固定时间格式,Mar 20 20:20:20 2016 print(time.ctime(16389348))--把时间戳转为这个格式 print(time.mktime(format))--print(time.mktime(time.localtime()))---转化为时间戳 (3)import datetime print(datatime.datetime.now())---2016-10-10 00:00:00 16893929
二、random模块(随机数)
(1)内置方法 print(random.random())--0-1之间的随机数 print(random.randint(1,8))--是一个范围值,整型,包括8 print(random.choice('hello'))---参数里的随机数,参数是序列 print(random.sample(序列))---随机在序列里取出多个 print(random.randrange(1,3))--里面参数也是一个范围值,随机在一范围内取一个不包括3 (2)生成验证码 生成5位数字验证码 def v_code(): code='' for i in range(5): add_num=random.randrange(10)----在0-10里取 code+=str(add_num) print(code) 生成数字带字母的验证码,数字如何变为字母?---有一个内置函数chr能把65-91的数字变为任意字母 def v_code(): code='' for i in range(5): add=random.choice([random.randrange(10),chr(random.randrange(65,91)]) print(code)
三、os模块(与系统交互)
(1)调用系统命令,常用的调用命令(windows与Linux都可以用,但参数路径不一样有的是\有的是/) import os print(os.getcwd())----打印当前系统windows的工作目录 print(os.chdir(r'C:\User'))---切换工作目录 print(os.curdir):相当于.返回当前目录 print(os.pardir):相当于..返回上级目录 print(os.makedirs('abc\\alex')):创建多级目录,多一个\表转义 print(os.removedirs('abc\\alex')):删除多级文件夹,如果这个文件夹里有文件就删不了了,它只能删空文件夹 print(os.mkdir('dirname')):只能生成一个文件夹,生成路径最后一个是文件夹 print(os.rmdir('dirname')):删除一个空文件夹 print(os.listdir(r'C:\User'))-----展示目录下的所有文件,其中r表示原生字符串,后面的参数没有特殊意思全是普通字符 print(os.remove('adc.txt')):删除文件 print(os.rename('oldname','newname')):给文件或目录重命名,可不带扩展名 print(os.stat('path/filename')):获取目录/文件信息,st_size=12:表文件大小,里面内容有多少 st_atime=124434341:文件最后访问时间 st_mtime=299239:修改时间 os.stat('path/filename').st_size print(os.sep):当前系统的路径分隔符不带()是变量名带()调用了是一个值,windows是\ linux是/,用它可以直接用这个值做分隔符 若k=os.sep C:kUserskAdmin print(os.linesep):windows用\r\n做转行符,linux用\n做转行符 print(os.pathsep):输出用于分割文件路径的字符串,eg:环境变量,windows用;做路径之间的分隔符,linux用:做环境变量分隔符 print(os.name):输出字符串指示当前使用平台,win--nt linux--posix print(os.system('bash command')):执行系统命名,windows与Linux的都行 print(os.environ):打印出现有的环境变量 *print(os.path.abspath('./abc')):打印某文件或目录的绝对路径 print(os.path.split(/path)):分隔出路径与文件名,做为一个元组 *print(os.path.dirname('C:\User\abc.txt')):打印某文件的绝对目录路径,不带文件 print(os.path.basename(path)):返回path最后的文件句 print(os.path.exists(path)):判断该路径是否存在,存在是true,不存在是false print(os.path.isabs(path)):如果path是绝对路径就返回true print(os.path.isfile(path)):如果path是一个存在的文件,返回true否则false print(os.path.isdir(path)):如果path是一个存在的目录,则返回true *print(os.path.join([path1 ,path2, ..] )):路径组合,将多个路径组合后返回, print(os.path.getatime(path)):返回path所指向文件或目录的最后存取时间 print(os.path.getmtime(path)):返回path所指向的文件或目录的最后修改时间
四、hashlib模块
加密,明文传密文(MD5加密,加密是唯一的,明文加密成密文都是一样的)
(1)加密方法(以下都是不可逆的) 1.md5加密 import hashlib m=hashlib.md5()--md5的对象 m.update('hello world'.encode('utf8'))---python3要做一个字符转换,
在Python3写的hello world是Unicon类型,要把它解码为字节类型(二进制,byte类型),
因为update参数必须是二进制数 m.digest()---转换成十进制,用print打印出来 m.hexdigest()--转换成十六进制 新加一个参数会在hello world的原值上基础上再加密 m.update('alex'.encode(utf8)) m.hexdigest() m.update('hello worldalex'.encode(utf8))---这个值就跟上一个值是一样的,说明是把字符更新后再一起加密的 2.sha加密(1 224 256 368,一般256用的多些) s=hashlib.sha256() s.update('hello world'.encode('utf8')) print(s.hexdigest())
五、logging模块,日志模块
1.原来写日志是打开一个文件用write写进去 2.import logging 日志级别:critical>error>warning>info>debug,以下内容直接打印只有后三个有显示,前二个级别不够,里面的参数是自己写的内容 logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message') 灵活配置日志级别,日志格式与输出位置,用模块的basicConfig方法 logging.basicConfig(level=logging.DEBUG,-----级别定为DEBUG format='%(asctime)s %(filename)s[line:%(lineno)d'] %(levelname)s %(message)'--%()里面的就是变量,这几个不是必须的,是自己定的需要什么打印什么 时间 文件 程序的行号 日志级别 记录内容 datefmt='%a, %d %b %Y %H:%M:%S',--表asctime的时间格式 filename='test.log'---表filename,可用绝对路径 filemode='w')---filename模式,写模式日志不会打印屏幕而是文件里,但程序执行完重新启动就把之前的删了,可以用a模式 format的其它参数: %(name)s:logger的名字 %(levelno)s:数字形式的日志级别 %(threadName)s:线程名,可能没有 logging.debug('debug message') 文件里打印的是fri,09 sep 2016 14:30:04 logging_module.py[line:10] DEBUG debug message logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message') 这里运行脚本打印的日志就会生成一个test.log记录这些日志信息,这里日志级别的方法能直接调用模块basicConfig的格式化生成对应的日志到文件里 这里面默认是打印在屏幕上的,如果加了filename就会写到文件里,只能有二种方式,但如果二个地方都要打印要如何做? 3.logger :模块级别的函数 import logging logger = logging.getLogger()---取出logger对象,这个对象是空的 fh = logging.FileHandler('test.log')--文件输出流对象,文件对象 ch = logging.StreamHandler()--屏幕对象 formatter = logging.Formatter('%(asctime)s-%(name)s'-%(levelname)s-%(message)s')--格式对象 fh.setFormatter(formatter)---文件打印的格式,setFormatter是fh对象的方法,把文件格式定好 ch.setFormatter(formatter)---屏幕打印的格式 logger.addHandler(fh)--把文件加进logger输出对象,文件又有自己的格式,添加进输出行为 logger.addHandler(ch)---把屏幕对象也加进loggerll输出对象,屏幕也有自己的格式 logger.setLevel(logging.DEBUG)---定日志级别 logger.debug('123') logger.info('456')--下面这二个执行时屏幕与文件里都有日志 4.日志级别 要定级别,如果是info那比info高的都打印,比它低的就不打印 logger.setLevel(logging.DEBUG)--定级别或上面的level=logging.DEBUG
六、sys模块
常用调用函数,与Python解释器进行交互的模块
import sys *print(sys.argw):命令行参数list,第一个元素是程序本身路径,打印出解释器后所有的参数 >>>python test.py 如果这个脚本里有上传下载如果与python交互,可以从后面加上参数 >>>python test.py post path:告诉python下载路径,这些参数个数不定,这些参数如取用sys.argw test.py print(sys.argw)---执行这个脚本时打印(test.py post path) if sys.argv[1]=='post' post()---用写的上传函数,执行test.py这个脚本时根据后面的参数来控制这个函数使用什么功能 print(sys.exit(n)):退出程序,正常退出时exit(0),退出本脚本 print(sys.version):获取python解释器版本信息 print(sys.maxint):最大的int值 *print(sys.path):返回模块的搜索路径,初始化使用PYTHONPATH环境变量的值 若在这个变量里添加路径print(sys.path.append(C:\users)) print(sys.platform):返回当前操作系统平台名称,作用:可以用这个做为跨平台判断,当它是win时可以调用os时写的路径就可以变了,这个程序就可以跨平台了 print(sys.stdout.write('please'))--终端上标准输出 print(sys.stdin.readline())
七、configparser模块
用于生成和修改常见配置文档,当前模块在python3变为configparser
(1)配置文件格式 [DEFAULT] ServerAliveInterval=45 fotmat=5 [other] form=ie 这是键值对的等式格式,如何生成? import configparser config = configparser.ConfigParser()---操作文件句柄对象里面没数据,现在是空数据,下面进行给对象赋值 config("DEFAULT") = {'ServerAliveInterval':'45','fotmat':'5'}---把DEFAULT做为键,后面的统一做为值 config("other") = {'form':'ie'} with open('conf.ini','w',encoding='utf8') as f: config.write(f)-----这时f写进的就是上面的配置文件 print(config.sections())---取出键,other。注:这里的DEFAULT不行,它是默认的 print(config.defaults())--能看到DEFAULT下面的二个值,生成一个元组的列表 print('other' in config)--true print(config['other']['form'])---ie for key in config['other']:--这个值是字典,但如果是config则表示的是键,DEFAULT other print(key)---form ServerAliveInterval fotmat--默认的也必须打出来 如何修改? import configparser config = configparser.ConfigParser()---文件句柄 config.remove_section('other') ---意思是删了other里的所有数据,但文件不能修改,就要加上后面进行修改 config.write(open('f2','w'))---改为另一个文件就修改就解决了 修改值 config.set('other','form','de')---可直接改文件里的值 删键下的对应的键 config.remove_option('other','form')---可直接把文件里的键的键删除 判断是否有对应字符串 print(config.has_section('lili'))--flase
八、re模块:正则模块,进行模糊匹配
(1)什么是正则表达式? 用于匹配字符串的,跟列表元组没有关系 (2)匹配方法,字符串提供的方法是完全匹配,如果要模糊匹配如下: import re 元字符 . :匹配单个字符,但不能代指换行符,如果字符串里有一个\换行符,它不行 'w..l' --结果worl看到的是匹配到的全部 ^ :以某内容开头的,结果是匹配到某内容 $:以某某结尾 re.findall('a..x$','iemsjalex')--['alex'] * :重复匹配,匹配前面0次或多次,{0,+oo}。re.findall('a.*li','fjkafalexli') + :重复匹配,匹配前面1次或多次 ab+ ---表a后有多个b才行,abbbb才是结果所以a也必须可有 a+b---aaaab等 ? :重复0次/1次 {}:里面表匹配次数'a{5}b'--重复5次a haaaaab,'a{1,3}b'--可以是一个范围 []:字符集,里面放的是字符的是或的关系,取消元字符的特殊功能,但(\ ^ -)例外 ret=re.findall('a[c,d]x','acx'):c或d ---结果['a','c','d'] ret=re.findall('[a-z]','adx'):adx三个都会匹配上,特殊字符-例外 ret=re.findall('[w,*]','adx'):*不表示重复的功能,只表示*自己 [^]:取反,[^t,x]--除了t,x.其它都是。^里面是全不是,不是绑定它紧后的 |:或,分组()时的用 '(as)|3' --匹配的是as如果3放前面就匹配的是3 ():分组, print(re.search('(as)+','sdjkfasas').group())--asas 组名:?P<组名> ret=re.search('?P<name>\d{3}','www123') 匹配出来的名字就是这个组名,可以取出这个组名 \:1.反斜杠后边跟元字符去除特殊功能 \.:表示一个. \\:re.findall(r'\\','adhfD\')---['\\'] 为什么是二个\\,在re模块里是\\表一个\,但python也会有特殊字符,在python中也是\\是一个\,当\\传给python就是二个\\变为一个\ 2.反斜杠后边跟普通字符实现特殊功能 \d:匹配任何十进制数,它相当于类[0-9] \D:匹配任何非数字字符,相当于[^0-9] \s:匹配任何空白字符。它相当于[ \t\n\r\f\v] \S:匹配任何非空白字符,它相当于[^ \t\n\r\f\v] \w:匹配任何字母数字字符,相当于[a-zA-Z0-9] print(re.findall('\w','I am a LIST')) \b:匹配一个特殊字符边界,也就是指单词和特殊字符间的位置,前后都是可以找到,\bI I\b print(re.findall('I','I am a LIST'))--会有二个I print(re.findall(r'I\b','I am a LIST')),\b是查到I+特殊字符的边界,['I'] ?:前面的* +等都是是贪婪匹配也是尽可能匹配,后面加?号使用其变成惰性匹配 ret=re.findall('abc*?','abcccc')----ab,*最少识别c 0次所以c不要了 (3)正则表达式的方法 1.查找全部:re.findall(pattern,string,flag)--re.findall('w\w{2}l','hello world')--['worl']生成列表 2.search查找第一个,返回一个对象,对象可以调用一个group方法:ret=re.search('sb','fjaskdsbfasjksb') --返回结果是个对象不 内容 ,如何可应出内容 print(ret.group())---就是满足条件的第一个结果sb,不是列表了 3.match():只在字符串开始匹配,同^,返回一个对象,可用group方法打印内容 re.match('asd','asdfhdsasd')--是一个对象 ,re.match('asd','asdfhdsasd').group() 4.split() 'asdf'.split('s')--字符串的这个方法是以s划分这个字符串 ret=re.split('k','djksal')--['dj','sal'] re.split('[k,s]','djksal')---这表示分二次,先以k来分,再用s来分第一次分出来的 5.sub():表替换,三个参数,把替换内容的那个内容替换成哪个内容**** re.sub('a..x','s..b','hfjasalexxdhf')--hfjass..bxdhf 6.compile():先把规则编译成对象,用这个对象调用方法 obj=re.compile('\.com')--里面是一个正则规则被编译 obj=findall('magedu.com') 7.finditer()---迭代器 ret=re.finditer('\d','ds3sy4784a') print(next(ret).group()) (4)计算器: 用python实现一个计算器,实现加减乘除及拓号优先解析 以下的数字是字符串:s='1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4/3)/(16-3*2))' 1.匹配最里层的括号 re.search('\('[^()]+\),s)--匹配到里面没有括号的括号 2.写计算器 import re def check(s):-检测表达式有没有错误 flag=True if re.findall('[a-zA-Z]',s) print('Invalid')--打印值 flag=False return flag def format(s): s1=s.replace(' ','')---空格变为空 s2=s.replace('++','+') def cal_mul_div(s): re.search('\d+\.?\d*[*/]\d+\.?\d*')------('\d+\.?\d* [*/] \d+\.?\d*') 整与字浮数 这个表乘除 x,y=re.split('[*/]',ret) if float(x)*float(y) else float(x)/float(y) if check(source): strs=format(source) while re.search('\('): strs=re.search('\([^()]+\)',strs).group() strs=cal_mul_div(strs): strs=cal_add_sub(strs):加减函数
九、json模块
(1)文件里只能写字符类型的,所以字典等类型不能直接写到文件 dic={1:'ti',2:'di'} f=open('test','w')---会报错 f.write(dic)---会报错,所以可以给dic做个str的转化 dic=str({1:'ti',2:'di'}) data=f.read() print(eval(data)['1'])--取值 (2)序列化:把对象(列表,字典,字符等)从内存中变成可存储或传输的过程称之为序列化, import json dic={'name':'alex','age':'18'} data=json.dumps(dic)---把字典变为另一个自己存储的对象 f=open('JSON_text','w') f.write(data) 取这个文件里的内容,用另一个脚本实现 f=open('JSON_text','r') data1=f.read(JSON_text) data2=json.loads(data1)----把序列化后的改回来 print(data['name']) json只有这二个方法,支持所有的普通数据类型,比如字典、列表等,能与其它语言互通,但它不能把函数与类序列化 那高级的数据类型序列化如何处理?用pickle,但它不能与其它语言互通 上面是dumps与loads方法,那dump与load与它们是什么区别 import json dic={'name':'alex','age':'18'} data=json.dump(dic,f)--这里把dic序列化再f给write写进去了 f.write(data) 取出: f=open('JSON_text','r') data1=json.loads(data1,f)----把序列化后的改回来,把f读出来 print(data['name'])
十、pickle模块---打把类与函数序列化
(1)例 import pickle def foo(): print('ok') data=pickle.dumps(foo) f=open('PICKLE_text','w') f.write(data) f.close() 拿出 f=open('PICKLE_text','r') data2=f.read(PICKLE_text) data2=pickle.loads(data2) print(data2())
十一、shelve模块
shalve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写.key必须为字符串
(1)可以变化对象的多少 import shelve f=shelve.open('SHELVE_text') f['info']={'name':'alex','age':'18'}---直接向文件写数据 f['info1']={'other':'heigh'} data=f.get('info') print(data) data=f.get('info','name') print(data)
十二、xml模块(相当于json序列化)
创建一个xml的文件xml_text <?xml version='1.0'?> <data> <country name='liechtenstein'>---标签 属性(name) <rank updated='yes'>2</rank> <year>2008</year> </country> <country name='panama'> <rank updated='yes'>3</rank> <year>2009</year> </country>--关闭 xml_test.py----如何处理xml配置文件 import xml.etree.ElementTree as ET tree= ET.parse('xml_test') root= tree.getroot()----结果最外层的data print(root.tag) 遍历xml文档 for child in root: print(child.tag,child.attrib)---结果:每个country里的属性name及值,country{'name':'liechtenstein'} for i in child:----遍历country里每个name里的标签 print(i.tag,i.text)---结果:rank 2 year 8,包含上步结果 只遍历year节点: for node in root.iter('year')---对year下的标签进行循环 print(node.tag,nade.text) 修改: for node in root.iter('year'): new_year=int(node.text)+1---每个year的值加1,把每个标签的值拿出来 node.text=str(new_year) node.set('updated','yes')---改属性,把year加个属性 最后写入数据,新生成一个文件 tree.write('xmltext.xml') 创建xml文件
十三、说明及实例
(1)一个.py文件就称之为一个模块,就是对相关函数进行分组 (2)分类:有三种 python标准库:python自己定义的标准库 第三方模块:非官方的 应用程序自定义模块 (3)模块调用:为了来组织函数 自己写的一个脚本,里有几个相关函数,cal.py def add(x,y) print x+y return x,y 1.写另一个脚本bin.py如何调用cal import sys import cal ---通过搜索路径找到cal后,实际上cal.py会把所有代码加载给cal这个变量,这个变量 print(cal.add(1,2))-----这个cal要在当前路径下才能找到并调用?路径如何找的? print(sys.path) cal通过sys调当前路径bin从cal里找,并调用里面的函数 模块里面的变量这个脚本里不能直接取出必须用cal这个变去引用print(cal.x)---1,所以里面的函数与变量都是要通过模块去调用 当一个模块里有很多函数,只用其中几个? 如果只用cal是所有的函数都加载进去,当用到里面特定的 from cal import add 这时可以直接用方法不用cal来调用了,print(add(1+3)---不用cal来调用 2. 若引用模块里多个函数 from cal import add,del---这里Python只加载了这二个函数,用cal调用变量x也不行没有加载进来 可直接调用 3.from cal import *---引用所有函数,下面可直接调用不同于直接import cal--这样会用cal.add来引用 如果本脚本里也自己定义了一个add的函数,下面直接调用会调谁的? 谁在代码前面就执行谁 (4)包(packge):为了目录来组织模块,包目录下会有个_init_py,为了区分是包还是文件夹的,有这个就是包 包怎么创建?右键---new--python package--创建一个包下面会自动生成_init_py,下面可以写很很多.py文件 eg: web(包) _init_py web2--也是包 _init_py logger.py bin.py(与web一级)如何调用logger from web.web2 import logger(模块) 从包中调模块这时就可以调用模块了,但如何调用模块里的函数? logger.add() _init_py的作用:import web(包)---直接执行_init_py这个模块,跟模块不同import cal是把cal都是加载了而import web只执行_init_py,根下面的.py没用 (5)例:ATM 一个项目有很多.py, ATM(普通目录) bin(包) _init_py bin.py--是程序的执行入口 from module import main main.main()---会报错找不到logger,原因,执行这个脚本是在bin这个包下而不是module所以找不到,可以在上面用sys把ATM路径加进来,但易写死 module(包)--逻辑相关代码 _init_py logger.py main.py import logger def main(): logger.logging() conf(包) _init_py bin.py里面的正确写法? 加如相对路径 import os print(os.path.abspath(_file_))---_file_:打印当前程序的路径 print(os.path.dirname(os.path.abspath(_file_))) BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(_file_))))---拿绝对路径 sys.path.attend(BASE_DIR) (6)if _name_=='_main_':让测试函数不执行 hello.py def foo(): print('hello') foo()----这就是测试这个函数能不能正常运行,当其它模块调用这个函数时会打印结果,而这个测试的也会打印 会引起问题,所以要加一个if _name_=='_main_',这时测试函数就不行执行了,除函数以外的代码都放这里 if _name_=='_main_' foo() (7)软件代码规范,目录的如何组织 Foo/ bin/-------存放项目的一些可执行文件,也可以用script也行 foo---程序入口 foo/---是一个包用于各功能函数,存放项目的所有源代码 tests/---用于测试 _init_py test_main.py _init_py main.py docs/---------存放一些文档 conf.py abc.rst setup.py--------安装,部署,打包的脚本 requirements.txt---存放软件依赖的外部Python包列表 README-------项目说明文件(readme)
ATM实例
思路:还款与购物是分开的 atm_test _init_.py bin _init_py atm.py--主逻辑 #内容 import os import sys base_dir=os.path.dirname(os.path.dirname(os.path.abspath(_file_))) print(base_dir) sys.path.append(base_dir)-----这步为了找atm_test,这样才能找到core里的main,包之间的引用要用到这个 from core import main---上能找到atm_test if _name_ == '_main_'-----直接进main里去跑,这个atm本身不跑了 main.run() manage.py conf--------------可以放一些初值,定义字典列表等,存数据,是可配置的 _init_py_ setting.py #内容 import ... BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(_file_))) DATABASE={ 'engine':'file_storage', 'name':'accounts' 'path':"%s/db"% BASE_DIR LOG_LEVEL=logging.INFO---日志级别,改配置可以现场调试 LOG_TYPES={ 'transaction':'transaction.log',---分日志文件 'access':'access.log', } TRANSACTION_TYPE={ 'repay':{'action':'plus','interest':0}---支付,动作与利息 'withdray:{'action':'winue','interest':0.05}--转帐 core---主要程序逻辑都在这个目录里 _init_.py accounts.py---用于从文件里加载和存储帐户数据 auth.py ----用于认证模块 #内容 retry_count=0 while user_data['is_authenticate'] is True and retry_count < 3: db_hadler.py---数据库连接引擎 logger.py---日志记录模块 #内容 import logging from conf import settings def logger(log_type) logger = logging.getLogger(log_type)---loging对象 logger.setLevel(settings.LOG_LEVEL)---等级,是conf里写的一个方法,是一个变量 ch = logging.StreanmHandler() ch.setLevel(settings.LOG_LEVEL) ch=logging.StreamHandler) ch.setLevel(settings.LOG_LEVEL) log_file='%s/log/%s'%(setting.BASE_DIR,settings.LOG_TYPES[log_type])---日志文件路径,是个拼接路径 fh = logging.FileHandler(log_file) fh.setLevel(setting.LOG_LEVEL) formatter = logging.Formatter('%(asctime)s'-%(name)s-%(levelname)s) ch.setFormatter(formatter) fh.setFormatter(formatter) logger.addHandler(ch) logger.addHandler(fh) returm logger main.py----主逻辑交互程序 #内容 user_data={ 'account_id':None, 'is_authenticate':False, 'account_data':None } import ... trans_logger=logger.logger('transaction')---去看logger.py,logger对象打印日志,登录的 access_logger=logger.logger('access')---交易的 def run() acc_data = auth.acc_login(user_data,access_logger)---用户认证与日志打印,这二个只是变量,但在用的时候用的是其它模块里的函数通过前面的赋值实现,在上面赋值 if user_data['is_authenticate']:---这个字典的值是真还是假 user_data['account_data']= acc_data interactive(user_data) transaction.py---记帐 还钱 取钱等所有与帐户金额相关信息 db---用户数据存储的地方 _init_.py accout_sample.py--生成一个初始帐户数据 #内容 import json acc_dic = { -------卡号信息 'id':1234, 'password':'abc', 'credit' :15000, 'balance':15000,--余额 'enroll_data':'2016-01-02', 'expire_data':'2021-01-01', 'pay_day':22,--还款信息 'status':0, } data=json.dumps(acc_dic) f=open('123.json','w') f.wrint(data)---------------数据写入到json文件里,不同卡可以写不同文件里,不然他们不能同时改 accounts--存各个用户数据,一个用户一个文件 123.json---一个用户帐户示例 log--日志目录 _init_.py access.log---用户访问与操作日志 transactions.log---所有交易日志 shopping_mall---电子商城程序 _init_.py 总结: 1.login---包含auth() 2.菜单(展示,选择)
十四、ssh客户端模块paramiko
详解:https://blog.csdn.net/Sxiaokun/article/details/124070120
十五、python对话框
详解:https://blog.csdn.net/weixin_44289254/article/details/121043821