python笔记7 logging模块 hashlib模块 异常处理 datetime模块 shutil模块 xml模块(了解)

 logging模块

日志就是记录一些信息,方便查询或者辅助开发

记录文件,显示屏幕

 

低配日志, 只能写入文件或者屏幕输出

屏幕输出

import logging

logging.debug('调试模式')     #默认只输出warning以上信息, 
logging.info('正常运行')
logging.warning('警告')
logging.error('错误')
logging.critical('系统崩溃')

WARNING:root:警告
ERROR:root:错误
CRITICAL:root:系统崩溃

写入文件

import logging
logging.basicConfig(
        level=logging.DEBUG,
        #level=10,  # 显示的级别
        format='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s',  # 显示格式
        datefmt='%Y %m %d',  # 日期
        filename='a.log',  # 默认是a模式, 就是使用的gbk 编码。
        # filemode='w'  #一般只用追加写入,不用写入 因此不用改写模式。
)

logging.debug('调试模式')         # 等于10
logging.info('正常运行')      # 等于20
logging.warning('警告')      # 等于30
logging.error('错误')        # 等于40
logging.critical('系统崩溃')    # 等于50

标配日志,可屏幕输出也可记录日志

import logging

# 创建logging对象
log = logging.getLogger()

# 创建文件对象
f1 = logging.FileHandler('file1.log', encoding='utf-8')
f2 = logging.FileHandler('file2.log', encoding='utf-8')

#创建屏幕对象
sh = logging.StreamHandler()

# 日志格式设置
format1 = logging.Formatter(
        fmt='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s',  # 显示格式
        datefmt='%Y-%m-%d %H:%M:%S',)    #显示时间设置
format2 = logging.Formatter(
        fmt='%(asctime)s %(filename)s %(levelname)s ',  # 显示格式
        datefmt='%Y-%m-%d %H:%M:%S',)    #显示时间设置
format3 = logging.Formatter(
        fmt='%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s',  # 显示格式
        datefmt='%Y-%m-%d %H:%M:%S',)   #显示时间设置
# 给创建的输出对象绑定格式
f1.setFormatter(format1)
f2.setFormatter(format2)
sh.setFormatter(format3)

#给log对象添加输出对象
log.addHandler(f1)
log.addHandler(f2)
log.addHandler(sh)

#设置级别
log.setLevel(20)
sh.setLevel(30)
f1.setLevel(30)
f2.setLevel(40)


logging.debug('调试模式')
logging.info('正常运行')
logging.warning('警告')
logging.error('错误')
logging.critical('系统崩溃')

高配日志

通过导入文件(字典的方式)写日志,Django

import os
import logging.config

# 定义日志的输出的格式
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' 
                  '[%(levelname)s][%(message)s]'  # 其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'

id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'

# 找到当前目录绝对路径 __file__
logfile_dir = os.path.dirname(os.path.abspath(__file__))  # log文件的目录的绝对路径
logfile_name = '高配版.log'  # log文件名
# # 如果不存在定义的日志目录就创建一个
# if not os.path.isdir(logfile_dir):
#     os.mkdir(logfile_dir)
# log文件的全路径
logfile_path = os.path.join(logfile_dir, logfile_name)
# log配置字典
# 第一层键值对的键固定的关键字不能改变。
LOGGING_DIC = {
    'version': 1,  # 版本
    'disable_existing-loggers': False,  # 禁用现有的log日志
    'formatters': {  # 定义三种不同的日志格式
        'standard': {  # 格式1
            'format': standard_format
        },
        'simple': {  # 格式2
            'format': simple_format
        },
        'id_simple_format': {  # 格式3
            'format': id_simple_format
        }
    },
    'filters': {},  # 过滤
    'handlers': {
        'console': {  # 打印到终端的日志
            'level': 'DEBUG',  # 日志级别
            'class': 'logging.StreamHandler',  # 类:打印到屏幕
            'formatter': 'simple'  # 日志的格式
        },
        'default': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
            'formatter': 'standard',  # 日志的格式
            'filename': logfile_path,  # 日志文件的绝对路径
            'maxBytes': 1024*1024*5,   # 日志大小5M,以bytes
            'backupCount': 5,  # 最多只有5个文件
            'encoding': 'utf-8',
        },
    },
    'loggers': {
        '': {
            'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
            'level': 'DEBUG',
            'propagate': True,  # 向上(更高level的logger)传递
        },
    },
}
logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
# # logging.config  # 将你写好的logging 字典 在导入logging.config后,传到logging模块中
logger = logging.getLogger()   # 生成一个log实例  通过字典自己设置的个性化的log对象

logger.info('正常运行状态')  # 记录该文件的运行状态

 hashlib模块

1.加密的类型必须是str

2.无论这个str多长,加密之后都是转化成等长度的数字.

3.无论在任何机器上,

不同的字符串加密后一定不同

import hashlib
 
ret = hashlib.md5()    #定义一个ret的对象
ret.update('wk'.encode('utf-8'))      #将字符串'wk'转为bytes 加密
print(ret.hexdigest())                 #查看转换后的密文

5d2bf8e6622cb88ca16a745dcf8153a0

用途:

1,对密码进行加密

md5加密

a.普通的md5加密

import hashlib


def encryption(passwd):                #加密函数
    ret = hashlib.md5()
    ret.update(passwd.encode('utf-8'))
    return ret.hexdigest()


def register():
    user = input('>>>')
    passwd = input('>>>')
    passwd = encryption(passwd)
    with open('ku', encoding='utf-8', mode='a') as f1:
        f1.write('{}|{}'.format(user, passwd))

register()

用户注册完登录时,将登陆的密码再次加密然后与存储的进行对比

b,加盐

import hashlib


def encryption(passwd):
    ret = hashlib.md5('加盐'.encode('utf-8'))           #在别人设置的密码前再加一串固定的字符,使md5不容易破译,但是如果别人知道你的盐是什么还是可以破译
    ret.update(passwd.encode('utf-8'))
    return ret.hexdigest()


def register():
    user = input('>>>')
    passwd = input('>>>')
    passwd = encryption(passwd)
    with open('ku', encoding='utf-8', mode='a') as f1:
        f1.write('{}|{}'.format(user, passwd))

register()

c.动态加盐

import hashlib


def encryption(user, passwd): 
    ret = hashlib.md5(user[::2].encode('utf-8'))          #加的盐为用户名字符的奇数字符
    ret.update(passwd.encode('utf-8'))
    return ret.hexdigest()


def register():
    user = input('>>>')
    passwd = input('>>>')
    passwd = encryption(user,passwd)
    with open('ku', encoding='utf-8', mode='a') as f1:
        f1.write('{}|{}'.format(user, passwd))


register()

sha加密

import hashlib


def encryption(user, passwd):
    ret = hashlib.sha1(user[::2].encode('utf-8'))              #与md5用法一样,把md5改为sha1
ret.update(passwd.encode(
'utf-8')) return ret.hexdigest() def register(): user = input('>>>') passwd = input('>>>') passwd = encryption(user,passwd) with open('ku', encoding='utf-8', mode='a') as f1: f1.write('{}|{}'.format(user, passwd)) register()

哈希的加密方法有很多,尾数越高,加密方法越复杂,效率越低

2.文件的校验

校验文件就是把文件的内容生成MD5值,把MD5值对比校验

校验文件

import hashlib
def file_hashlib(file):
    ret = hashlib.md5()
    with open(file,mode='rb') as f1:
        ret.update(f1)
        return ret.hexdigest()
file_hashlib('文件')

校验可以累加

import hashlib
s1 = '蹦沙卡拉卡'                        #一个字符串一次性读取和分次读取其生成的MD5值一样(必须是相同字符串)
ret = hashlib.md5()
ret.update(s1.encode('utf-8'))
print(ret.hexdigest()) 

ret = hashlib.md5()
ret.update(''.encode('utf-8'))
ret.update(''.encode('utf-8'))
ret.update(''.encode('utf-8'))
ret.update(''.encode('utf-8'))
ret.update(''.encode('utf-8'))
print(ret.hexdigest())  

5f46742e84df43713d132852859aa3bb
5f46742e84df43713d132852859aa3bb

对于大文件每次读取一行,按行累加校验

import hashlib
def file_hashlib(file):
    ret = hashlib.md5()
    with open(file,mode='rb') as f1:
        for i in f1:             # 循环每行读取
            ret.update(i)
        return ret.hexdigest()
file_hashlib('文件')

异常处理

 异常发生后下边的代码就不再执行了

单支情况  try except

name                      #单有一个变量名运行

Traceback (most recent call last):                #报错
  File "F:/python24期/python/123.py", line 1, in <module>
    name
NameError: name 'name' is not defined           #报错 NameError

try--except: 尝试着运行try里面的代码,出现错误,按照错误类型去寻找相应的except,找到执行except里的代码,然后程序继续运转.

try:                    #代码可以运行并且不报错
    print(555)
    name                  #出现错误即跳转到except,不在往下执行
    print(666)  
except NameError:            #定义错误类型 
    print('name name is not defined')
print(777)

555                                         #错输出结果可见,try里的 错误代码下的代码不执行, 遇到错误后看except是否有指定错误,如果有,执行except里的代码,
name name is not defined
777

上述方法只能锁定一个错误,如果错误没有在except里,则程序还会报错  

try:
    print(555)
    l1 = [1, 2, 3]                   
    print(l1[10])         #打印列表的第10个参数,但是列表里只有2个参数    此时报IndexError错误
    print(666)
except NameError:             #except里没有定义IndexError错误,因此程序执行到print(l1[10])还是会报错并终止程序
    print('name name is not defined')
print(777)

Traceback (most recent call last):
555
  File "F:/python24期/python/123.py", line 4, in <module>
    print(l1[10])
IndexError: list index out of range

多支情况 try except except except ......

try:
    print(555)
    name
    l1 = [1, 2, 3]
    print(l1[10])
    print(666)
    dic = {'name': 'alex'}
    print(dic['age'])
except NameError:                         #定义多个except,但是还是try里的代码,遇到错误即停止往下执行
    print('name name is not defined')
except IndexError:
    print('索引超出范围....')
except KeyError:
    print('没有此key...')
print(777)

555
name name is not defined
777

万能处理  Exception

如果你对错误原因不关心,只是想不让其报错,那么程序中你就用万能处理.

如果你对错误原因需要进行不同分流或者程序处理,那么就需要多分支.

try:
    print(555)
    name
    l1 = [1, 2, 3]
    print(l1[10])
    print(666)
    dic = {'name': 'alex'}
    print(dic['age'])
except Exception as e:         #Exception可以接收所有错误, as e 把错误结果赋值给e
    print(e)
print(777)

555
name 'name' is not defined
777

多分支加万能处理 

try:
    print(555)
    name
    l1 = [1, 2, 3]
    print(l1[10])
    print(666)
    dic = {'name': 'alex'}
    print(dic['age'])
except NameError:                         #定义多个except,
    print('name name is not defined')
except IndexError:
    print('索引超出范围....')
except KeyError:
    print('没有此key...')
except Exception as e:                    #前边分流接收,最后以Exception 收尾
    print(e)
print(777)

try  except  else

try:
    print(555)
    name
except NameError:
    print('name name is not defined')
else:                                     #如果try里报错并且执行except,则代码往下走不执行else
    print(999)
print(777)

555                  #输出结果没有执行else里的代码
name name is not defined
777



try: print(555) name = 123 except NameError: #如果try里的代码没有报错,并且没有执行except,则执行else里的代码 print('name name is not defined') else: print(999) print(777) 555 999                    #此处执行了else里的代码 777

try  finally   

finaly 不管对与错都执行finally 但是代码不会继续往下走, 

try:
    name = 123
finally:
    print(777)
try:
    li = [1,2,3] 
    print(li[10])
finally:
    print(666)
print(888)                #print(888)没有执行


Traceback (most recent call last):
777                #不管对错finally内的代码都执行了
666
  File "F:/python24期/python/123.py", line 7, in <module>
    print(li[10])
IndexError: list index out of range

常作用于关闭文件,关闭连接,关闭数据库等等

f1 = open('a.log', encoding='utf-8')
f1.read()
'''
各种对文件操作的代码,但是可能会出错,出错之后,你的文件句柄无法关闭。
'''
f1.close()

# 解决方案: try: f1 = open('a.log', encoding='gbk') f1.read() f1.write('sfdsf') ''' 各种对文件操作的代码,但是可能会出错,出错之后,你的文件句柄无法关闭。 ''' finally: print(666) f1.close()

try  findally也可以作用于函数

def aa(x):
    try:
        c = x + 1
        return c
    finally:                      #finally作用于函数先执行finally再执行return
        print(666)
print(aa(1))

666          #先执行的findlly
2            #再执行的c=2

try except finally 

try:
    name = 123
finally:
    print(777)
try:
    li = [1,2,3]
    print(li[10])
except Exception:
    pass
finally:
    print(666)
print(888)

777
666
888

自定义异常处理

python提供了大部分异常,但是不是所有,比如 大的框架的手机连接问题,网络引发的代码问题等等.

Exception 也处理不了.

class PhoneConnectionError(BaseException):      #定义一个类,继承BaseException 类
    pass
raise PhoneConnectionError('错误类型')        #raise报一个指定的错误,此错误必须定义class PhoneConnectionError(BaseException):才能出现

Traceback (most recent call last):
  File "F:/python24期/python/123.py", line 5, in <module>
    raise PhoneConnectionError('错误类型')
__main__.PhoneConnectionError: 错误类型          #PhoneConnectionError的错误

要想让except能够找到自定义的错误类型,需要自定义一个错误类并且继承BaseException累

class PhoneConnectionError(BaseException):               #如果出现python解决不了的错误类型,就定义一个错误类,让这个类继承BaseException
    pass
try:
    raise PhoneConnectionError('错误类型')
except PhoneConnectionError:
    print('手机连接出现了问题')

手机连接出现了问题

assert  断言  只要条件不成立就报错

assert 1 == 2              #源码中经常遇到 只要条件不成立,我就抛出错误

Traceback (most recent call last): File "F:/python24期/python/123.py", line 1, in <module> assert 1 == 2 AssertionError

datetime模块

获取当前时间

import datetime
now_time = datetime.datetime.now()
print(now_time)

2019-01-10 19:49:42.388032

获取3周之后和3周之前的当前时间

import datetime
print(datetime.datetime.now())    
print(datetime.datetime.now()+datetime.timedelta(weeks=3))    #3周之后的时间
print(datetime.datetime.now()+datetime.timedelta(weeks=-3))   #3周之前的时间

2019-01-10 19:55:01.222595
2019-01-31 19:55:01.222595
2018-12-20 19:55:01.222595    

获取其他时间

import datetime
print(datetime.datetime.now())
print(datetime.datetime.now()+datetime.timedelta(days=3))   #3天后
print(datetime.datetime.now()+datetime.timedelta(days=-3))  #3天前
print(datetime.datetime.now()+datetime.timedelta(hours=3))  #3小时后
print(datetime.datetime.now()+datetime.timedelta(hours=-3)) #3小时前
print(datetime.datetime.now()+datetime.timedelta(minutes=3))  #3分钟后
print(datetime.datetime.now()+datetime.timedelta(minutes=-3)) #3分钟前
print(datetime.datetime.now()+datetime.timedelta(seconds=3))  #3秒后
print(datetime.datetime.now()+datetime.timedelta(seconds=-3)) #3秒前

2019-01-10 19:59:35.137924
2019-01-13 19:59:35.137924
2019-01-07 19:59:35.137924
2019-01-10 22:59:35.137924
2019-01-10 16:59:35.137924
2019-01-10 20:02:35.137924
2019-01-10 19:56:35.137924
2019-01-10 19:59:38.137924
2019-01-10 19:59:32.137924

可直接调整到年月日时分秒

import datetime 
current_time = datetime.datetime.now()
print(current_time.replace(year=1977))  # 直接调整到1977年
print(current_time.replace(month=1))  # 直接调整到1月份
print(current_time.replace(year=1989,month=4,day=25))  # 1989-04-25 18:49:05.898601


1977-01-10 20:03:57.756185
2019-01-10 20:03:57.756185
1989-04-25 20:03:57.756185

将时间戳转化成时间

import datetime
print(datetime.date.fromtimestamp(1232132131))

2009-01-17

shutil模块

对普通文件操作

高级的 文件、文件夹、压缩包 处理模块

shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中

import shutil

shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))

shutil.copyfile(src, dst)
拷贝文件

shutil.copyfile('f1.log', 'f2.log') #目标文件无需存在

shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变

shutil.copymode('f1.log', 'f2.log') #目标文件必须存在

shutil.copystat(src, dst)
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('f1.log', 'f2.log') #目标文件必须存在

shutil.copy(src, dst)
拷贝文件和权限

import shutil

shutil.copy('f1.log', 'f2.log')

shutil.copy2(src, dst)
拷贝文件和状态信息

import shutil
shutil.copy2('f1.log', 'f2.log')

shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹

import shutil
 
shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) #目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 

shutil.rmtree(path[, ignore_errors[, onerror]])递归的去删除文件

import shutil

shutil.rmtree('folder1')

shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。

shutil.move('folder1', 'folder3')

打包压缩

shutil.make_archive(base_name, format,...)

创建压缩包并返回文件路径,例如:zip、tar

创建压缩包并返回文件路径,例如:zip、tar

      • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
        如 data_bak                       =>保存至当前路径
        如:/tmp/data_bak =>保存至/tmp/
      • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
      • root_dir: 要压缩的文件夹路径(默认当前目录)
      • owner: 用户,默认当前用户
      • group: 组,默认当前组
      • logger: 用于记录日志,通常是logging.Logger对象
#将 /data 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("data_bak", 'gztar', root_dir='/data')
  
  
#将 /data下的文件打包放置 /tmp/目录
import shutil
ret = shutil.make_archive("/tmp/data_bak", 'gztar', root_dir='/data')

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:

import zipfile

# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()

# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall(path='.')
z.close()

zipfile压缩解压缩


import tarfile

# 压缩
>>> t=tarfile.open('/tmp/egon.tar','w')
>>> t.add('/test1/a.py',arcname='a.bak')
>>> t.add('/test1/b.py',arcname='b.bak')
>>> t.close()


# 解压
>>> t=tarfile.open('/tmp/egon.tar','r')
>>> t.extractall('/egon')
>>> t.close()

tarfile压缩解压缩

xml模块(了解)

 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,
大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
现在这种格式的文件比较少了,但是还是存在的所以大家简单了解一下,以备不时之需。

xml文件

<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

xml数据

xml文件
# 增删改查
# 在进行操作之前,都应该进行这两步:

# import xml.etree.ElementTree as ET
# tree = ET.parse('a.xml')  # 形成树形结构
# root = tree.getroot()  # 得到树的根系
# print(root)
# 循环打印:
# for i in root:
#     print(i)
# <Element 'country' at 0x00000196B51191D8>
# <Element 'country' at 0x00000196B5124B88>
# <Element 'country' at 0x00000196B5124D18>

# 所有的增删改查都是基于这个root根系去操作

# 查:
# 1,全文搜索 year 将所有的year标签全部找
# print(root.iter('year'))
# print([i for i in root.iter('year')])
# 2,只找第一个,找到就返回
# print(root.find('country'))
# 3,在root的子节点找,找所有的
# print(root.findall('country'))

# 练习
# 找到标签也可以找到标签相应的内容:tag,attrib,text

# 1,找所有的rank标签,以及 attrib 和 text (这里利用列表推导式比较方便)
# print([i for i in root.iter('rank')])
# [<Element 'rank' at 0x000001367D0D49F8>, <Element 'rank' at 0x000001367D0D4BD8>, <Element 'rank' at 0x000001367D0D4D68>]
# print([i.attrib for i in root.iter('rank')])
# [{'updated': 'yes'}, {'updated': 'yes'}, {'updated': 'yes'}]
# print([i.text for i in root.iter('rank')])  # ['2', '5', '69']

# 2,找到第二个country的 neighbor标签以及他的属性
# print([tag for tag in root.findall('country')][1].find('neighbor').attrib)
# {'direction': 'N', 'name': 'Malaysia'}


# 增 append
# import xml.etree.ElementTree as ET
# tree = ET.parse('a.xml')  # 形成树形结构
# root = tree.getroot()  # 得到树的根系

# 给 year 大于2010年的所有标签下面添加一个month标签,属性为name:month 内容为30days

# for country in root.findall('country'):
#     for year in country.findall('year'):
#         if int(year.text) > 2010:
#             month = ET.Element('month')
#             month.text = '30days'
#             month.attrib = {'name': 'month'}
#             country.append(month)
# tree.write('b.xml')

#

# import xml.etree.ElementTree as ET
# tree = ET.parse('a.xml')  # 形成树形结构
# root = tree.getroot()  # 得到树的根系
# 对所有的year属性以及值进行修改
# for node in root.iter('year'):
#     new_year=int(node.text)+1
#     node.text=str(new_year)
#     node.set('updated','yes')
#     node.set('version','1.0')
# tree.write('test.xml')


#
# import xml.etree.ElementTree as ET
# tree = ET.parse('a.xml')  # 形成树形结构
# root = tree.getroot()  # 得到树的根系
#
# # 将 rank值大于50的country标签删除
# for country in root.findall('country'):
#    rank = int(country.find('rank').text)
#    if rank > 50:
#      root.remove(country)
#
# tree.write('output.xml')

对xml的增删改查简单操作
import xml.etree.ElementTree as ET
 
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True)
 
ET.dump(new_xml) #打印生成的格式

自己创建xml文档

  

原文地址:https://www.cnblogs.com/ywrj/p/10241156.html