typing模块
一 前言
Python是一门弱类型的语言,很多时候我们可能不清楚函数参数类型或者返回值类型,很有可能导致一些类型没有指定方法,在写完代码一段时间后回过头看代码,很可能忘记了自己写的函数需要传什么参数,返回什么类型的结果,就不得不去阅读代码的具体内容,降低了阅读的速度,typing模块可以很好的解决这个问题。
python3.5以上版本,typing模块提高代码健壮性
二 typing模块的作用
- 类型检查,防止运行时出现参数和返回值类型不符合。
- 作为开发文档附加说明,方便使用者调用时传入和返回参数类型。
- 该模块加入后并不会影响程序的运行,不会报正式的错误,只有提醒。
注意:typing模块只有在python3.
5
以上的版本中才可以使用,pycharm目前支持typing检查
三 typing模块的常用方式
from typing import List, Tuple, Dict def test(a: int, string: str, f: float, b: bool) -> Tuple[List, Tuple, Dict, bool]: ll=[1,2,3,4] tup = (string, a, string) dic = {"xxx": f} boo = b return ll, tup, dic, boo print(test(12, "lqz", 2.3, False))
注意:
-
在传入参数时通过“参数名:类型”的形式声明参数的类型;
-
返回结果通过"-> 结果类型"的形式声明结果的类型。
-
在调用的时候如果参数的类型不正确pycharm会有提醒,但不会影响程序的运行。
-
对于如list列表等,还可以规定得更加具体一些,如:“-> List[str]”,规定返回的是列表,并且元素是字符串。
三 typing常用的类型
-
int,long,float: 整型,长整形,浮点型;
-
bool,str: 布尔型,字符串类型;
-
List, Tuple, Dict, Set:列表,元组,字典, 集合;
-
Iterable,Iterator:可迭代类型,迭代器类型;
-
Generator:生成器类型;
四 python天生支持多态,迭代器中的元素可能多种
from typing import List, Union def func(a: int, string: str) -> List[int or str]: list1 = [] list1.append(a) list1.append(string) return list1 def get_next_id() -> Union[int, None]: return 1 return None # 使用or关键字表示多种类型,也可以用Union
一 什么是uuid
uuid是128位的全局唯一标识符(univeral unique identifier),通常用32位的一个字符串的形式来表现。有时也称guid(global unique identifier),C#语言中使用。python中自带了uuid模块来进行uuid的生成和管理工作
- UUID —— Universally Unique IDentifier Python中称为 UUID
- GUID —— Globally Unique IDentifier C#中称为 GUID
它是通过MAC地址、 时间戳、 命名空间、 随机数、 伪随机数来保证生成ID的唯一性,,有着固定的大小( 128 bit位 ),通常由 32 字节的字符串(十六进制)表示
它的唯一性和一致性特点,使得可以无需注册过程就能够产生一个新的UUID;UUID可以被用作多种用途, 既可以用来短时间内标记一个对象,也可以可靠的辨别网络中的持久性对象
二 uuid有什么用
很多应用场景需要一个id,但是又不要求这个id 有具体的意义,仅仅用来标识一个对象。常见的用处有数据库表的id字段;用户session的key值;前端的各种UI库,因为它们通常需要动态创建各种UI元素,这些元素需要唯一的id, 这时候就需要使用UUID了。例如:一个网站在存储视频、图片等格式的文件时,这些文件的命名方式就可以采用 UUID生成的随机标识符,避免重名的出现
三 Python中uuid模块
UUID主要有五个算法,也就是五种方法来实现
python的uuid模块提供的UUID类和函数uuid1(),uuid3(),uuid4(),uuid5() 来生成1, 3, 4, 5各个版本的UUID ( 需要注意的是:python中没有uuid2()这个函数)。
- uuid.uuid1(node clock_seq)
# 基于时间戳
# 使用主机ID, 序列号, 和当前时间来生成UUID, 可保证全球范围的唯一性.
# 但由于使用该方法生成的UUID中包含有主机的网络地址, 因此可能危及隐私.
# 该函数有两个参数, 如果 node 参数未指定, 系统将会自动调用 getnode() 函数来获取主机的硬件(mac)地址.
# 如果 clock_seq 参数未指定系统会使用一个随机产生的14位序列号来代替.
import uuid
print(uuid.uuid1())
- uuid.uuid3(namespace, name)
# 通过计算名字和命名空间的MD5散列值得到,保证了同一命名空间中不同名字的唯一性,
# 和不同命名空间的唯一性,***但同一命名空间的同一名字生成相同的uuid****。
print(uuid.uuid3(uuid.NAMESPACE_URL,'python'))
print(uuid.uuid3(uuid.NAMESPACE_URL,'python'))
- uuid.uuid4() : 基于随机数
# 通过随机数来生成UUID. 使用的是伪随机数有一定的重复概率. print(uuid.uuid4())
- uuid.uuid5(namespace, name)
# 通过计算命名空间和名字的SHA-1散列值来生成UUID, 算法与 uuid.uuid3() 相同 print(uuid.uuid5(uuid.NAMESPACE_URL,'python'))
四 总结
1 Python中没有基于 DCE 的,所以uuid2可以忽略
2 uuid4存在概率性重复,由无映射性
3 若在Global的分布式计算环境下,最好用uuid1
4 若有名字的唯一性要求,最好用uuid3或uuid5
subprocess模块
subprocess模块允许你去创建一个新的进程让其执行另外的程序,并与它进行通信,获取标准的输入、标准输出、标准错误以及返回码等。更多查看官网:https://docs.python.org/2/library/subprocess.html?highlight=subprocess#frequently-used-arguments
import subprocess import subprocess ''' sh-3.2# ls /Users/nick/Desktop |grep txt$ mysql.txt tt.txt 事物.txt ''' res1 = subprocess.Popen('ls /Users/jieli/Desktop', shell=True, stdout=subprocess.PIPE) res = subprocess.Popen('grep txt$', shell=True, stdin=res1.stdout, stdout=subprocess.PIPE) print(res.stdout.read().decode('utf-8')) # 等同于上面,但是上面的优势在于,一个数据流可以和另外一个数据流交互,可以通过爬虫得到结果然后交给grep res1 = subprocess.Popen('ls /Users/jieli/Desktop |grep txt$', shell=True, stdout=subprocess.PIPE) print(res1.stdout.read().decode('utf-8')) # windows下: # dir | findstr 'test*' # dir | findstr 'txt$' res1 = subprocess.Popen(r'dirC:\Users\Administrator\PycharmProjects\test\函数备课', shell=True, stdout=subprocess.PIPE) res = subprocess.Popen('findstr test*', shell=True, stdin=res1.stdout, stdout=subprocess.PIPE) # subprocess使用当前系统默认编码,得到结果为bytes类型,在windows下需要用gbk解码 print(res.stdout.read().decode('gbk'))
shutil模块
高级的文件、文件夹、压缩包处理模块。
import shutil # shutil.copyfileobj(fsrc, fdst[, length]),将文件内容拷贝到另一个文件中 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),拷贝文件和权限 shutil.copy('f1.log', 'f2.log') # shutil.copy2(src, dst),拷贝文件和状态信息 shutil.copy2('f1.log', 'f2.log') # shutil.ignore_patterns(*patterns) # shutil.copytree(src, dst, symlinks=False, ignore=None),递归的去拷贝文件夹 # 目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除 shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) # shutil.rmtree(path[, ignore_errors[, onerror]]),递归的去删除文件 shutil.rmtree('folder1') # shutil.move(src, dst),递归的去移动文件,它类似mv命令,其实就是重命名 shutil.move('folder1', 'folder3') # shutil.make_archive(base_name, format, ...),创建压缩包并返回文件路径,例如: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/目录 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()
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()
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>
Python使用xml
xml协议在各个语言里的都 是支持的,在python中可以用以下模块操作xml:
# print(root.iter('year')) #全文搜索 # print(root.find('country')) #在root的子节点找,只找一个 # print(root.findall('country')) #在root的子节点找,找所有 import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #遍历xml文档 for child in root: print('========>', child.tag, child.attrib, child.attrib['name']) for i in child: print(i.tag, i.attrib, i.text) #只遍历year 节点 for node in root.iter('year'): print(node.tag, node.text) #--------------------------------------- import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() #修改 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') #删除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml') #在country内添加(append)节点year2 import xml.etree.ElementTree as ET tree = ET.parse("a.xml") root = tree.getroot() for country in root.findall('country'): for year in country.findall('year'): if int(year.text) > 2000: year2 = ET.Element('year2') year2.text = '新年' year2.attrib = {'update': 'yes'} country.append(year2) #往country节点下添加子节点 tree.write('a.xml.swap')
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) #打印生成的格式