Python基础 ( 九 ) —— 模块之 os、json、re、logging等

时间:2022-08-19 22:38:43

#os模块

import os,sys print(os.path.abspath(__file__))      #获取一个文件的绝对路径(此处括号内为__file__,代表获取此执行文件的绝度路径)
print(os.getcwd())                    #获取当前工作路径
os.chdir('package0')                  #改变当前工作路径
os.chdir('..')                        #改变工作路径到上一层
os.makedirs('dir1/dir2/dir3')         #递归生成文件夹
os.removedirs('dir1/dir2/dir3')       #删除文件并返回上一层,若上一层目录为空,则也删除并再返回上一层
os.rmdir('dir11')                     #删除单个文件夹(目录),为空则无法删除
os.remove('111.py')                   #删除单个文件
print(os.listdir('module_test'))      #以列表形式列出当前目录下所有文件名,不填值默认为当前工作路径
print(os.stat('test'))                #查看指定文件具体信息
Python基础 ( 九 ) —— 模块之 os、json、re、logging等
print(os.sep)                         #获取当前操作系统的分隔符,win下为\\,linux下为/
a=os.linesep                          #获取当前操作系统的换行符,win下\r\n,linux下\n
print(os.pathsep)                     #获取当前操作系统的路径分隔符(如环境变量路径的分隔),win下为 ; ,linux下 :
os.system('dir')                      #运行shell命令
print(os.path.split(__file__))        #将path分隔成目录和文件名,以二元组返回
print(os.path.dirname(__file__))      #返回path的目录,即os.path.split()的第一项
print(os.path.basename(__file__))     #返回path最后的文件名,如果最后以\或/结尾就会返回空值
print(os.path.exists('test'))         #判断path是否存在,返回一个bool值
print(os.path.isabs('test'))          #判断path是否是绝对路径
print(os.path.isdir('package0'))      #判断path是否是目录
a = 'C:\\Users\\Administrator\\.PyCharm2018.3'    #以系统分隔符拼接路径
b = 'config\\scratches\\text.py' c = os.path.join(a,b) print(c)

#sys模块

import sys print(sys.path)             #获取系统环境变量
print(sys.platform)         #获取系统平台名称
print(sys.version)          #获取python解释器版本
sys.exit(0)                 #退出程序,正常退出为exit(0)

#sys.argv()                                     获取程序输入变量

Python基础 ( 九 ) —— 模块之 os、json、re、logging等

 #模拟一个进度条

import sys,time for i in range(30): sys.stdout.write('#')         #向终端屏幕输出'#',print函数就是由这个写的
    time.sleep(0.1) sys.stdout.flush() #刷新缓存,加载到屏幕上

#json模块 (用作任何语言之间的数据交换)                    #重要

#相当于eval的升级版

#用json模块,字符串统一用双引号 " "

#json转换后的类型其他语言都能用

#json.dumps工作流程:将所有'' 变为"",再转换为字符串

#json.loads 还原数据类型

import json dic={"name":"alex"} dic_str = json.dumps(dic)          #这里其实已经是json字符串(其他语言都能用)
with open('json','w') as f1: f1.write(dic_str) with open('json','r') as f2: dic1=json.loads(f2.read()) #还原数据类型 print(type(dic1)) print(dic1)

 #json.dump

import json dic={"name":"alex"} with open('json','w') as f: json.dump(dic,f) #以上相当于
import json dic={"name":"alex"} with open('json','w') as f: f.write(json.dumps(dic))

#json.load 和上同理

import json dic={"name":"alex"} with open('json','r') as f: print(json.load(f)) #等同于
import json dic={"name":"alex"} with open('json','r') as f: print(json.loads(f.read()))

#pickle模块

(可以用来把实例化的对象存入文本中,以后也能调用,具体看面向对象的大作业那节)

#使用方法完全与json模块一样,功能也一样,但只能用于python,不能用于其他语言

#不同在于json把对象处理成字符串,pickle处理成字节,故文件打开是需要用到b模式('rb','wb'...)

import pickle dic={"name":"alex"} print(type(pickle.dumps(dic)))  #<class 'bytes'>

#序列化(将对象的信息转换为可以存储或传输的形式bytes):pickle.dumps()

import pickle dic={"name":"alex"} with open('pickle','wb') as f: f.write(pickle.dumps(dic))

#反序列化:pickle.loads()

 #shelve模块

import shelve f=shelve.open('shelve')                    #打开一个名字为shelve的特殊文件用于存放字典(文件内容无需看),f为文件句柄
f['shelve']={'123'}                        #往里面存入字典
f['info']={'name':'alex','age':'18'} print(f.get('shelve'))                     #用f.get取出字典里的内容
print(f.get('info')['name']) f.close()

#xml模块  (xml文件,存放标签语言)

 #比json模块出现的早,也是用于数据交换

#读取xml文档

import xml.etree.ElementTree as ET           #将次模块记为 ET ,方便下面调用 (import xxx as xxx)
tree = ET.parse("xml_lesson.xml") root = tree.getroot()                        #获取根节点(根对象)

#tag方法(获取对象名(标签))

import xml.etree.ElementTree as ET           #将次模块记为 ET ,方便下面调用 (import xxx as xxx)
tree = ET.parse("xml_lesson.xml") root = tree.getroot()                        #获取根节点(根对象)
print(root.tag)                              #获取根对象的标签
for i in root:                               #遍历根对象,得到子节点(对象)
    print(i) print(i.tag)                             #获取子节点的标签
    for j in i : print(j.tag)                         #获取子节点内容的标签

#attrib方法(获取标签对象属性,形式为键值对)

import xml.etree.ElementTree as ET           #将次模块记为 ET ,方便下面调用 (import xxx as xxx)
tree = ET.parse("xml_lesson.xml") root = tree.getroot()                        #获取根节点(根对象)
print(root.attrib)                           #获取根对象的属性(这里为空)
for i in root:                               #遍历根对象,得到子节点(对象)
    print(i.attrib)                          #获取子节点的属性
    print(i.attrib['name'])                  #取出value

#text方法(获取标签对象的实际内容)

import xml.etree.ElementTree as ET tree = ET.parse("xml_lesson.xml") root = tree.getroot() for i in root: for j in i: print(j.text)                          #获取标签对象的内容

#root.iter()方法   :遍历获取指定对象

import xml.etree.ElementTree as ET tree = ET.parse("xml_lesson.xml") root = tree.getroot() for i in root.iter('year'):                  #遍历root,只拿出year
    print(i.tag,i.text)                      #打印标签名和内容

#tree.write() : 将整个xml 树写入新文件(修改操作)

import xml.etree.ElementTree as ET tree = ET.parse("xml_lesson.xml") root = tree.getroot() for i in root.iter('year'): i.text = '修改的标签值'                     #这里都只是在内存中修改
    i.set('这是标签属性名','这是标签属性值') tree.write('xml_new.xml',encoding='utf8')       #修改后写入新文本

#findall()-->找多个对象;find()找单个对象;root.remove-->删除对象

import xml.etree.ElementTree as ET tree = ET.parse("xml_lesson.xml") root = tree.getroot() for i in root.findall('country'):                 #找出root下所有country对象
    rank = int(i.find('rank').text)               #找到country对象中的rank的值
    if rank > 50 :                                #删除rank大于50的country对象
 root.remove(i) tree.write('xml_new.xml',encoding='utf8')

#创建xml文档

import xml.etree.ElementTree as ET namelist = ET.Element('namelist')                                              #创建主节点
name = ET.SubElement(namelist,'name',attrib={'这是属性名':'这是属性值'})       #创建副节点
name.text='这是副节点值' et=ET.ElementTree(namelist)                                                    #生成文档对象(那颗树)
et.write('newxml.xml',encoding='utf8',xml_declaration=True)

 #re模块(正则表达式)

#用于处理字符串,模糊匹配

#re是一种小型的、高度专业化的编程语言(由C语言编写)任何编程语言都有

#正则的核心:元字符 . ^ $ + ? {} [] | () \

#re.findall()         -->匹配所有满足条件的内容,但不能有重叠,如下应用

#通配符 .

#可以匹配任何字符,除了换行符\n,一个 . 代表一个字符

import re print(re.findall('a...b','adfadfjblakjdb'))

# ^  -->以什么开头

print(re.findall('^a..b','adfbdfjblakj'))

# $  -->以什么结尾

print(re.findall('a..b$','adfbdfjblakjb'))

#四个重复匹配符号

# * 匹配靠近的字符0到无穷次(匹配的字符可以一个都没有,也就是匹配0次)

# + 匹配靠近的字符1 到 无穷次(匹配的字符必须有一个,也就是匹配1次)

print(re.findall('abc*','aaaabdd'))     #匹配到'ab'
print(re.findall('abc+','aaaabdd'))     #未匹配到

#以上* + ?都为贪婪匹配,即按最多匹配最多的次数,后面加?改成惰性匹配(通用,{}后加也行)

# ? 匹配0或1 次

# {}   匹配次数由你定

print(re.findall('abc?','aaaabccccdd'))
print(re.findall('abc{0,1}','aaaabcccccccdd'))       #相当于 ?
print(re.findall('abc{0,}','aaaabcccccccdd'))        #匹配0到无穷次 ,相当于 *
print(re.findall('abc{5}','aaaabcccccccdd'))         #匹配5次
print(re.findall('abc{1,4}?','aaaabcccdd'))      #改为惰性匹配
 

#字符集 []       里面没有特殊符号(- ^ \ 除外),所有都为字符

#  - 代表XXX到XXX

print(re.findall('abc[cd]','aaaabcccdd'))               #[] 里代表c或d
print(re.findall('abc[cd xb]','abcxxabccdcdd'))
print(re.findall('x[a-z]','xaaaabcccdd'))               #[a-z] 代表匹配的一个字符 ,a-z 代表 a到z的字母 ,
print(re.findall('x[a-z]*','xaaaabcccdd666'))

# ^ 代表 非

print(re.findall('x[^a-z]*','xaaaabcccdd666'))

# \  转译符  (放在字符之前代表把一个元字符变成普通字符,或者把普通字符变得有意义)

\d 匹配所有数字 0到9

\D 匹配所有非数字字符

\s 匹配任何空白字符

\S 匹配任何非空白字符

\w 匹配任何字母数字字符(包括_)

\W匹配任何非字母数字

\b 匹配一个特殊字符边界 

import re print(re.findall('I\\b','111 I am 222I333'))        #\b代表匹配的特殊字符(如空格)或边界字符
                                                    #这里写\\b(\\代表去掉了python解释器里\的特殊意义,变为一个普通的\)是因为在python解释器中\b已有特殊意义,与re模块的重复了
print(re.findall(r'I\b','111 I am 222I333'))        #这里的r 代表对于后面的字符串,python解释器不做任何转译,于是就用来re模块里的转译

 

#把元字符变为普通字符

 

import re print(re.findall('a\\\\c','a\c'))                     #首先python解释器里,\\\\转译成两个普通的\\,然后在re模块里,\\转译为一个普通\
                                                      #匹配结果为['a\\c'],因为匹配到的是re里的\,到python解释器里,又转译为\\
print(re.findall(r'a\\c','a\c'))                      #或者用r不让python解释器做转译

 

#取出最里面括号的内容
print(re.findall('\([^()]*\)','12+5*(7-6*(3-1))'))

# () 代表分组 | 代表或

print(re.findall('ab|c','abcdac'))                      # | 代表 或 (ab 或 c)
print(re.findall('(abc)+','abcccc'))                    # 只匹配到abc

 

#search 方法

#区别与findall,同样是查找,但search只匹配一次(找到第一个匹配的),且返回的是一个对象

 

a = re.search('\d+','adsf213dfa4213dd')                 #返回 <re.Match object; span=(4, 7), match='213'>
print(a.group())                                        #取出对象内容

 

#分组

b = re.search('(?P<name>[a-z]+)(?P<age>\d+)','alex30ssy18') #固定写法(?P<组名>匹配的内容) 用于把匹配的内容分组 
print(b.group('name'),b.group('age'))                       #取出匹配内容里的指定组

 # match 方法 

#从开始进行匹配,相当于search里加 ^

print(re.match('\d','adf213'))           #匹配不到

#split 方法

#以指定字符串分隔

print(re.split('ab','adffabdfsdsf'))                      #以指定字符串分隔

#sub、subn(替换完并把替换次数写出) 方法

#替换

print(re.sub('\d+','B','adf23123adfs'))                     #sub('被替换的字符串(找到所有的)','替换的内容','总的内容')
                                    
#如果想替换指定次数,sub()第四个参数写上次数
print(re.sub('\d','B','adf23123adfs',1))

#compile 方法

func=re.compile('\d+')                                      #将匹配需求保存成对象
print(func.findall('adsf231fa3'))                

#finditer 方法

a=re.finditer('\d+','213dsfa2')                        #跟findall一模一样,只是返回的不是列表而是迭代器
print(a.__next__().group())

#小补充

import re print(re.findall('www\.(163)\.com','123www.163.comfadsf'))    #用()分组后,解释器会默认觉得你所关注的内容为组的内容,于是只返回组的值(如这里是163)
print(re.findall('www\.(?:163)\.com','123www.163.comfadsf'))  #()里的内容前面加上?:可以去掉优先级 #还有如下例子
print(re.findall('123','123123123'))              #['123', '123', '123']
print(re.findall('(123)+','123123123'))           #['123'] 括号的优先级认为你只关注与括号内的123,于是只显示123
print(re.findall('(?:123)+','123123123'))         #['123123123']

 #利用正则实现eval进行四则运算的功能(重要!!!!!!!!!!!!!) 如:

#   '(5 + 40.1 / 5 * ((6+4*4) * 5 - (5+4))+6*7)*2/5+1'

import re
def calc(a):
    a = a.replace(' ','')                         #消去空格
    b = re.findall('[^+\-]+[*/]+[^+\-]+',a)       #查找乘除部分
    num = []
    for i in b :
        d = re.split('[*/]',i)
        e = re.findall('[*/]',i)
        for j in e :
            if j == '*':
                d[1] = (float(d[0]))*(float(d[1]))
                del d[0]
            elif j == '/' :
                pass
                d[1] = (float(d[0]))/(float(d[1]))
                del d[0]
        num.append(d[0])
    A = re.split('[+\-]',a)
    for k,l in enumerate(A) :
        if re.findall('[*/]+',l) :
            A[k] = num[0]
            del num[0]
        else :
            A[k]=float(A[k])
    n = re.findall('[+\-]+', a)
    for o in n :
        if o == '+' :
            A[1] = A[0]+A[1]
            del A[0]
        elif o == '-' :
            A[1] = A[0]-A[1]
            del A[0]
    return [A[0]]
def eval_new(x):
    x = x.replace(' ', '')
    if x.count('(') == x.count(')') and (not re.findall('[+\-*/]{2,}',x)) and re.findall('[\d)]{1}',x[-1]):
        while True :
            a = re.findall('\([^()]+\)',x)
            if not a :
                print(calc(x)[0])
                break
            else:
                for num,i in enumerate(a) :
                    b = re.sub('[()]','',i)
                    c = calc(b)
                    x = x.replace(i,str(c[0]))
    else :
        print('表达式有误')

print(eval('(5 + 40.1 / 5 * ((6+4*4) * 5 - (5+4))+6*7)*2/5+1'))         #343.808
eval_new('(5 + 40.1 / 5 * ((6+4*4) * 5 - (5+4))+6*7)*2/5+1')            #343.808

 

 #logging模块 (日志模块)

#分为五个级别,debug、info、warning、error、critical (级别依次升高)

#指定那个级别,就把那个级别之上的(包括自己)给显示出来(默认显示如下)

Python基础 ( 九 ) —— 模块之 os、json、re、logging等

#basicConfig设置

import logging logging.basicConfig( level=logging.DEBUG,             # 设定显示级别为debug,注意大写,不设置默认为warning级别
    filename='logging.log',          # 设置日志信息保存文件,如果不写这项则输出到屏幕
    filemode='w', format='%(asctime)s %(lineno)d %(message)s %(filename)s'            #1、内容改为asctime时间2、输出显示各级别信息的行号3、日志信息
)                                                                       #4、该代码文本的文件名
 logging.debug('debug message') logging.info('info message') logging.warning('warning message') logging.error('error message') logging.critical('critical message')

 #以上执行结果如下

Python基础 ( 九 ) —— 模块之 os、json、re、logging等

 #format参数

Python基础 ( 九 ) —— 模块之 os、json、re、logging等

 #Logger

def logger_func():                                         #定义成函数,方便调用(可以存成文本再别的文件中调用)
    logger=logging.getLogger() #指定功能的对象
    fh=logging.FileHandler('文件名')                        #向文件输出
    ch=logging.StreamHandler()                             #向屏幕输出
    fm=logging.Formatter('%(asctime)s %(message)s')        #格式化输出,可以任意制定格式
    #调用以上功能
    fh.setFormatter(fm)                                    #获取fm的格式,不写此行代码就以默认的格式输出
    ch.setFormatter(fm)                                    #同上 logger.setLevel('DEBUG')                               #设置级别,要大写
 logger.addHandler(fh)                    #调用fh的功能 logger.addHandler(ch)                    #调用ch的功能 return logger logger=logger_func()                                       #把函数的返回值logger赋值给logger
 logger.debug('debug message') logger.info('info message') logger.warning('warning message') logger.error('error message') logger.critical('critical message')

#逻辑图如下

Python基础 ( 九 ) —— 模块之 os、json、re、logging等

#注意!!!如果要设置多个子对象,命名一定不能重复,以下例子说明(错误示范)

import logging logger1=logging.getLogger('name')             #得到一个子对象,并命名为name(不写默认为root),注:创建子对象的子对象用 name.son
logger2=logging.getLogger('name')             #这里logger1 logger2重名了
 ch=logging.StreamHandler() logger1.setLevel('CRITICAL') logger2.setLevel('WARNING')                   #因为logger1 logger2重名,所以第二个设置直接覆盖了第一个设置
 logger1.addHandler(ch) logger2.addHandler(ch) logger1.debug('debug message')                  #输出logger1设置下的日志
logger1.info('info message') logger1.warning('warning message') logger1.error('error message') logger1.critical('critical message') logger2.debug('debug message')                  #输出logger2设置下的日志
logger2.info('info message') logger2.warning('warning message') logger2.error('error message') logger2.critical('critical message')

#父对象输出时,会把所有子对象也输出

import logging logger1=logging.getLogger() logger2=logging.getLogger('son') logger3=logging.getLogger('son.son') fh=logging.FileHandler('文件名') ch=logging.StreamHandler() logger1.setLevel('CRITICAL') logger2.setLevel('ERROR') logger3.setLevel('WARNING') logger1.addHandler(fh) logger2.addHandler(fh) logger3.addHandler(fh) logger1.addHandler(ch) # logger2.addHandler(ch) # logger3.addHandler(ch)
 logger1.debug('11111debug message') logger1.info('1111info message') logger1.warning('1111warning message') logger1.error('1111error message') logger1.critical('1111critical message') logger2.debug('2222debug message') logger2.info('222info message') logger2.warning('2222warning message') logger2.error('2222error message') logger2.critical('222critical message') logger3.debug('3333debug message') logger3.info('333info message') logger3.warning('333warning message') logger3.error('333error message') logger3.critical('333critical message')

#如果没有 输出到文件或屏幕,则默认输出到屏幕。若不想输出到屏幕,则需要输出到文件里并不写输出到屏幕的相应代码才行!!!!!!!!!!!!!!!!!!!!