在柞水等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供网站设计、成都网站制作 网站设计制作按需求定制制作,公司网站建设,企业网站建设,成都品牌网站建设,网络营销推广,外贸网站制作,柞水网站建设费用合理。
目录
StringIO、BytesIO:...1
路径操作,pathlib:...2
OS模块:...10
shutil模块:...13
文件拷贝:...13
rm..14
mv.14
StringIO:
io模块中的类;
from io import StringIO;
内存中,开辟的一个文本模式的buffer,可以像文件对象一样操作它(仅在内存中,在内存中构建文件);
当close()方法被调用的时候,这个buffer会被释放;
sio=StringIO();sio.getvalue(),获取全部内容,跟文件指针没有关系,无视指针,输出全部内容;
好处,一般来说,磁盘的操作比内存的操作要慢得多,内存足够的情况下,一般的优化思路是少落地,减少磁盘IO的过程,可以大大提高程序的运行效率;
通常解决方案,单机用StringIO,多机分布式用redis;
BytesIO:
io模块中的类;
from io import BytesIO;
内存中,开辟的一个二进制模式的buffer,可以像文件对象一样操作它;
当close()方法被调用的时候,这个buffer会被释放;
file-like对象:
类文件对象,可以像文件对象一样操作;
socket对象、输入输出对象(stdin,stdout),都是类文件对象;
与unixOS一样,一切皆文件;
例:
In [63]: from io import StringIO
In [64]: sio = StringIO()
In [65]: print(sio.readable(),sio.writable(),sio.seekable())
True True True
In [66]: sio.write('magedu\npython')
Out[66]: 13
In [67]: sio.seek(0)
Out[67]: 0
In [68]: sio.readline()
Out[68]: 'magedu\n'
In [69]: sio.readline()
Out[69]: 'python'
In [70]: sio.getvalue() #无视指针,输出全部内容,相当于sio.seek(0);sio.read()
Out[70]: 'magedu\npython'
In [71]: sio.close()
例:
In [72]: from io import BytesIO
In [73]: bio=BytesIO()
In [74]: print(bio.readable(),bio.writable(),bio.seekable())
True True True
In [75]: bio.write('magedu\npython'.encode())
Out[75]: 13
In [76]: bio.seek(0)
Out[76]: 0
In [77]: bio.readlines()
Out[77]: [b'magedu\n', b'python']
In [78]: bio.getvalue()
Out[78]: b'magedu\npython'
In [79]: bio.close()
例:
In [80]: from sys import stdout
In [81]: f=stdout
In [82]: type(f)
Out[82]: _io.TextIOWrapper
In [83]: f
Out[83]: <_io.TextIOWrapper name='
In [84]: f.write('magedu.com') #同import sys;sys.stdout.write('magedu.com'),print('magedu.com),print也是调用控制台(标准输出)打印
Out[84]: magedu.com
3.4版本之前用os.path,from os import path;
os.path.join('/etc/','sysconfig','network')
os.path.exists(p)
os.path.abspath(p)
os.path.dirname(p)
os.path.basename(p)
os.path.split(p)-->(head,tail),返回二元组,head为dirname,tail为basename;
os.path.splitdrive(p)-->(head,tail),仅win下用,取驱动器;
例:
In [1]: from os import path
In [2]: p=path.join('/etc','sysconfig','network') #os.path后的方法是操作字符串
In [3]: p
Out[3]: '/etc/sysconfig/network'
In [4]: type(p) #字符串对象
Out[4]: str
In [5]: path.exists(p)
Out[5]: True
In [6]: path.split(p)
Out[6]: ('/etc/sysconfig', 'network')
In [7]: path.abspath('.')
Out[7]: '/home/python/magedu/projects/cmdb'
win下:
注:
win下识别/和\,最好用r'c:\nt';
linux下仅识别/;
3.4版本开始,更加的面向对象:
pathlib模块,建议使用;
from pathlib import Path #提供Path对象,来操作目录和文件,第一个字母大写(大驼峰);
p=Path()
p.absolute()
p.joinpath('subpath2','subpath3')
p /= 'subpath2' / 'subpath3'
p.exists()
路径拼接:
方一:
操作符/;
Path对象 / Path对象;
Path对象 / 字符串;
字符串 / Path对象;
方二:
p.joinpath(*other),连接多个字符串到Path对象中;
方三:
p.absolute().joinpath('subpath2','subpath3') / 字符串或Path对象
路径分解:
p.parts #parts属性,可以返回路径中的每一个部分;
p.absolute().parts
获取路径:
str(p) #获取路径字符串;
bytes(p) #获取路径字符串的bytes;
父目录:
p.parent #目录的逻辑父目录,常用于获取某个文件的路径;相对路径的父目录要先转绝对路径,不转绝对路径父目录是其本身;
p.parent.parent #到头后,不报错;
p.parents #父目录序列,索引0是直接的父;逐级到根(从长到短);
p.name,目录的最后一个部分;
p.stem,目录最后一个部分,没有后缀;
p.suffix,目录最后一个部分的扩展名;
p.suffixes,返回多个扩展名列表;
p.with_suffix(suffix)-->新路径,补充扩展名到路径尾部,返回新的路径,扩展名存在则无效;
p.with_name(name)-->新路径,替换目录最后一个部分,并返回一个新的路径;相当于p = p.parent / 'name';
完整路径两种:
完整路径 = p.parent + p.name
完整路径 = p.parent + p.stem + p.suffix
p.cwd(),返回当前工作目录;
p.home(),返回当前用户目录;
p.is_dir(),是否是目录,OS上要有实体;
p.is_file(),是否是普通文件;
p.is_symlink(),是否是软链接;
p.is_socket(),是否是socket文件;
p.is_block_device(),是否是块设备文件;
p.is_char_device(),是否是字符设备文件;
p.is_absolute(),是否是绝对路径;
p.resolve()-->新路径,返回一个新路径,这个新路径就是当前Path对象的绝对路径,如果是软链接则直接被解析;
p.absolute(),获取绝对路径,推荐使用p.resolve();
p.exists(),目录或文件是否存在;
p.rmdir(),删除空目录,没有提供判断目录为空的方法;
p.touch(mode=0o666,exist_ok=True),创建一个文件,0o为八进制;
p.as_uri(),将路径返回成uri,如file:///etc/hosts;
p.mkdir(mode=0o777,parents=False,exist_ok=False),
如p.mkdir(parents=True)相当于mkdir -p,若parents=False父目录不存在则抛FileNotFoundError;
exist_ok,3.5版本加入,False时路径存在抛FileExistsError,True时FileExistsError被忽略,一般不用此项,写前用if判断路径是否存在;
p.iterdir(),迭代当前目录;
p.glob(pattern),通配给定的模式;
p.rglob(pattern),通配给定的模式,recursion递归目录;
p.match(pattern),匹配;
p.open(mode='r',buffering=-1,encoding=None,errors=None,newline=None),使用方法同内建函数open(),返回一个文件对象;
3.5版增加的新函数:
p.read_text(encoding=None,errors=None)
p.read_bytes(),以rb方式读取路径对应文件,并返回二进制流;
p.write_bytes(data),以wb方式写入数据到路径对应文件;
p.write_text(data,encoding=None,errors=None),以wt方式写入字符串到路径对应文件;
例:
In [8]: from pathlib import Path
In [9]: p=Path() #实例化,当前目录,同set(),dict(),list()等
In [10]: type(p) #linux下为pathlib.PosixPath,win下为pathlib.WindowsPath
Out[10]: pathlib.PosixPath
In [11]: p
Out[11]: PosixPath('.')
In [12]: p.absolute()
Out[12]: PosixPath('/home/python/magedu/projects/cmdb')
In [13]: p=p.joinpath('a','b') #同p=p / 'a' / 'b'
In [14]: p.absolute()
Out[14]: PosixPath('/home/python/magedu/projects/cmdb/a/b')
In [15]: p = p / 'c' / 'd' #同p /= 'c' / 'd',等号右边必须要有Path对象p
In [16]: p
Out[16]: PosixPath('a/b/c/d')
In [17]: p.absolute()
Out[17]: PosixPath('/home/python/magedu/projects/cmdb/a/b/c/d')
In [18]: p1=Path('/etctest') #初始化绝对路径,实际不存在
In [19]: p1
Out[19]: PosixPath('/etctest')
In [20]: p1.exists()
Out[20]: False
In [21]: p2=Path()
In [22]: p2=p1 / 'sysconfig' #等号右边必须要有Path对象,不可以p2='/etctest' / 'sysconfig'
In [23]: p2
Out[23]: PosixPath('/etctest/sysconfig')
In [24]: print(p2) #与p2结果一样,但调用的函数不一样,p2作为字符串用时要强制类型转换str(p2)
/etctest/sysconfig
In [25]: p=Path('a','b','c/d') #当前目录下的a/b/c/d
In [26]: p
Out[26]: PosixPath('a/b/c/d')
In [27]: p=Path('/a','/b','c') #错误,当前路径要慎用
In [28]: p #路径为/b/c
Out[28]: PosixPath('/b/c')
In [29]: p.parts
Out[29]: ('/', 'b', 'c')
In [30]: print(str(p),bytes(p)) #bytes(p)同str(p).encode()
/b/c b'/b/c'
例:
In [33]: p=Path('/etc/sysconfig/network')
In [34]: p.parent
Out[34]: PosixPath('/etc/sysconfig')
In [35]: p.parent
Out[35]: PosixPath('/etc/sysconfig')
In [36]: p.parent.parent
Out[36]: PosixPath('/etc')
In [37]: p.parent.parent.parent
Out[37]: PosixPath('/')
In [38]: p.parent.parent.parent.parent
Out[38]: PosixPath('/')
In [39]: list(p.parents)
Out[39]: [PosixPath('/etc/sysconfig'), PosixPath('/etc'), PosixPath('/')]
In [40]: list(p.parents)[0]
Out[40]: PosixPath('/etc/sysconfig')
In [41]: next(iter(p.parents)) #注意超界
Out[41]: PosixPath('/etc/sysconfig')
In [42]: for x in p.parents:
...: print(x)
...:
/etc/sysconfig
/etc
/
In [43]: p=Path()
In [44]: p.parent #相对路径的父目录是其本身
Out[44]: PosixPath('.')
In [45]: p.absolute().parent #相对路径的父目录先转绝对路径,再查看
Out[45]: PosixPath('/home/python/magedu/projects')
In [46]: p.absolute().parent.parent
Out[46]: PosixPath('/home/python/magedu')
In [48]: for x in p.absolute().parents:
...: print(x)
...:
/home/python/magedu/projects
/home/python/magedu
/home/python
/home
/
例:
In [49]: p=Path('/etc/sysconfig/test.txt')
In [50]: p.name
Out[50]: 'test.txt'
In [51]: p.stem
Out[51]: 'test'
In [52]: p.suffix
Out[52]: '.txt'
In [53]: p.suffixes
Out[53]: ['.txt']
In [54]: p2=Path('/etc/sysconfig/test.tar.gz')
In [55]: p2.suffixes
Out[55]: ['.tar', '.gz']
In [56]: p2.with_suffix('.bz2') #修改扩展名一定要带点,原.gz-->.bz2,否则ValueError: Invalid suffix 'bz2';若原扩展名没点,经此操作是加扩展名
Out[56]: PosixPath('/etc/sysconfig/test.tar.bz2')
In [57]: p2.with_suffix('.tgz')
Out[57]: PosixPath('/etc/sysconfig/test.tar.tgz')
In [58]: p3=Path('/etc/sysconfig/test')
In [59]: p3.with_suffix('.tgz')
Out[59]: PosixPath('/etc/sysconfig/test.tgz')
In [60]: p2.with_name('test') #改文件名,同p2 = p2.parent / 'test'
Out[60]: PosixPath('/etc/sysconfig/test')
In [61]: p3.with_name('test.tar.gz')
Out[61]: PosixPath('/etc/sysconfig/test.tar.gz')
In [64]: p3
Out[64]: PosixPath('/etc/sysconfig/test')
In [65]: p3.with_suffix('.tgz')
Out[65]: PosixPath('/etc/sysconfig/test.tgz')
In [67]: p3=p3.parent / 'test.tgz'
In [68]: p3
Out[68]: PosixPath('/etc/sysconfig/test.tgz')
例:
In [69]: p=Path('a','b','c/d')
In [70]: p.mkdir(parents=True)
In [71]: p.exists()
Out[71]: True
例:
In [1]: from pathlib import Path
In [2]: p=Path()
In [3]: p.iterdir()
Out[3]:
In [4]: p.iterdir()
Out[4]:
In [5]: for x in p.iterdir():
...: if x.is_dir():
...: print(x)
...:
a
In [6]: p
Out[6]: PosixPath('.')
In [7]: ls
a/ max-min.sh test test.txt
例:
遍历,并判断文件类型,如果是目录并判断其是否为空;
from pathlib import Path
p = Path('a/b/c/d')
for x in p.parents[len(p.parents)-1].iterdir():
print(x,end='\t\t\t\t')
if x.is_dir():
flag = False
for _ in x.iterdir():
flag = True
break
print('dir','Not Empty' if flag else 'Empty',sep='\t\t\t\t')
elif x.is_file():
print('file')
else:
print('other file')
例:
In [24]: p=Path()
In [25]: p
Out[25]: PosixPath('.')
In [27]: p.glob('t*')
Out[27]:
In [28]: list(p.glob('t*'))
Out[28]: [PosixPath('test'), PosixPath('test.txt')]
In [30]: list(p.glob('/*.py')) #错误,p是当前路径,通配的是/下的文件
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
----> 1 list(p.glob('/*.py'))
……
In [31]: list(p.glob('*/*.py'))
Out[31]: []
In [32]: list(p.glob('**/*.py')) #**/相对当前的,之后任意级
Out[32]: [PosixPath('pathlib_Path_iterdir.py')]
In [33]: p.resolve() #绝对路径,软链接会追踪
Out[33]: PosixPath('/home/python/magedu/projects/cmdb')
In [35]: list(p.rglob('*.py'))
Out[35]: [PosixPath('pathlib_Path_iterdir.py')]
In [38]: !touch e/test.py
In [42]: p=Path('e/test.py')
In [43]: p.match('*.py')
Out[43]: True
In [44]: Path('.py').match('*.py')
Out[44]: True
In [45]: Path('a/b/c.py').match('b/*.py')
Out[45]: True
In [46]: Path('a/b/c.py').match('a/*.py')
Out[46]: False
In [47]: Path('a/b/c.py').match('a/*/*.py')
Out[47]: True
In [48]: Path('a/b/c.py').match('a/**/*.py')
Out[48]: True
In [49]: Path('a/b/c.py').match('**/*.py')
Out[49]: True
In [50]: Path('a/c.py').match('a/*/*.py')
Out[50]: False
In [51]: Path('a/c.py').match('a/**/*.py')
Out[51]: False
例:
In [52]: p=Path('/tmp/test.txt')
In [53]: p.touch()
In [54]: p.open('w+')
Out[54]: <_io.TextIOWrapper name='/tmp/test.txt' mode='w+' encoding='UTF-8'>
In [55]: with p.open('w+') as f: #建议使用with...as...
...: f.write('test\ntest')
...:
In [56]: f
Out[56]: <_io.TextIOWrapper name='/tmp/test.txt' mode='w+' encoding='UTF-8'>
In [57]: f.closed
Out[57]: True
In [58]: p.read_text()
Out[58]: 'test\ntest'
In [59]: p.write_text('abc') #每次都会清空再写,不能传模式
Out[59]: 3
In [60]: p.read_text()
Out[60]: 'abc'
os.name,win显示nt,linux显示posix;
os.uname(),win不支持,linux支持;
os.listdir('/tmp'),返回目录内容列表,是立即返回;
sys.platform,win显示win32,linux显示linux;
os.stat(path, *, dir_fd=None, follow_symlinks=True),
调用linux系统的stat,
path,路径的string或bytes或fd;
follow_symlinks=True默认追踪,返回文件本身信息,False如果是软链接则显示软链接本身;
os.chmod(path,mode,*,dir_fd=None,follow_symlinks=True)
os.chown(path,uid,gid),改变文件的属主、属组、但需要有足够的权限;
注:
os也有open、read、write等方法,太低级(底层),建议使用内建函数open、read、write;
例:
In [61]: import os
In [62]: os.name
Out[62]: 'posix'
In [63]: os.uname
Out[63]:
In [64]: os.uname()
Out[64]: posix.uname_result(sysname='Linux', nodename='tmsapp', release='2.6.32-431.el6.x86_64', version='#1 SMP Sun Nov 10 22:19:54 EST 2013', machine='x86_64')
In [65]: os.listdir('/tmp')
Out[65]:
['keyring-c8Fi6u',
'+~JF1728020691866336530.tmp',
'.X11-unix',
……
In [66]: import sys
In [67]: sys.platform
Out[67]: 'linux'
例:
]$ ln -sv test.txt t1
`t1' -> `test.txt'
]$ ln -sv test.txt t2
`t2' -> `test.txt'
]$ stat test.txt
File: `test.txt'
Size: 66 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 1448511 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 504/ python) Gid: ( 504/ python)
Access: 2018-05-04 06:53:48.943903498 +0800
Modify: 2018-03-14 15:44:32.618152979 +0800
Change: 2018-03-14 15:44:32.628153003 +0800
]$ stat -L t1
File: `t1'
Size: 66 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 1448511 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 504/ python) Gid: ( 504/ python)
Access: 2018-05-04 06:53:48.943903498 +0800
Modify: 2018-03-14 15:44:32.618152979 +0800
Change: 2018-03-14 15:44:32.628153003 +0800
]$ stat -L t2
File: `t2'
Size: 66 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 1448511 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 504/ python) Gid: ( 504/ python)
Access: 2018-05-04 06:53:48.943903498 +0800
Modify: 2018-03-14 15:44:32.618152979 +0800
Change: 2018-03-14 15:44:32.628153003 +0800
In [1]: import os
In [2]: os.stat('test.txt')
Out[2]: os.stat_result(st_mode=33204, st_ino=1448511, st_dev=64768, st_nlink=1, st_uid=504, st_gid=504, st_size=66, st_atime=1525388028, st_mtime=1521013472, st_ctime=1521013472)
In [3]: os.stat('t1')
Out[3]: os.stat_result(st_mode=33204, st_ino=1448511, st_dev=64768, st_nlink=1, st_uid=504, st_gid=504, st_size=66, st_atime=1525388028, st_mtime=1521013472, st_ctime=1521013472)
In [4]: os.stat('t2')
Out[4]: os.stat_result(st_mode=33204, st_ino=1448511, st_dev=64768, st_nlink=1, st_uid=504, st_gid=504, st_size=66, st_atime=1525388028, st_mtime=1521013472, st_ctime=1521013472)
In [5]: os.stat('t1',follow_symlinks=False)
Out[5]: os.stat_result(st_mode=41471, st_ino=1444349, st_dev=64768, st_nlink=1, st_uid=504, st_gid=504, st_size=8, st_atime=1525415800, st_mtime=1525415780, st_ctime=1525415780)
In [6]: oct(33204)
Out[6]: '0o100664' #八进制
In [7]: oct(41471)
Out[7]: '0o120777'
高级文件操作;
打开2个文件对象,源文件读取内容,写入目标文件来完成拷贝过程(只内容一样),这样会丢失stat数据信息(元数据信息等,包括权限),因为根本没有复制过去;
import shutil
shutil.copyfileobj(fsrc,fdst[,length=16384]),文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容,fdst要求可写,length表示buffer的大小;
shutil.copyfile(src,dst,*,follow_symlinks=True),复制文件内容,不含元数据,src,dst为文件路径的字符串,本质上调用的是shutil.copyfileobj()不带元数据二进制内容复制;
shutil.copymode(src,dst,*,follow_symlinks=True),仅复制权限;
shutil.copystat(src,dst,*,follow_symlinks=True),复制元数据,stat中包含的所有东西,另ctime改不了或不会改;
shutil.copy(src,dst,*,follow_symlinks=True),复制文件内容、权限和部分元数据,不包括创建时间和修改时间,本质上调用的是shutil.copyfile()和shutil.copymode();
shutil.copy2(src,dst,*,follow_symlinks=True),比shutil.copy()多了复制全部元数据,但需要平台支持,本质上调用的是shutil.copyfile()和shutil.copystat();
shutil.copytree(src,dst,symlinks=False,ignore=None,copy_function=copy2,ignore_dangling_symlinks=False),递归复制目录,默认使用copy2,即带更多的元数据复制,
src,dst必须是目录,src必须存在,dst必须不存在;
ignore=func,提供一个callable(src,names)-->ignored_names函数,它会被调用,src是源目录,names是os.listdir(src)的结果,即列出src中的文件名,返回值是要被过滤的文件名的set类型数据;
shutil.rmtree(path,ignore_errors=False,onerror=None),
同rm -rf,慎用,递归删除;
它不是原子操作,有可能删除错误就会中断,但已经删除的就删了;
ignore_errors为True,忽略错误,为False或Omitted时,onerror生效;
onerror为callable,接受函数function、path、execinfo;
shutil.move(src,dst,copy_function=copy2),
递归移动文件、目录到目标,返回目标;
本身使用的是os.rename方法;
如果不支持remove,如果是目录则是copytree再删除源目录;
默认使用copy2方法;
shutil还有打包功能,生成tar并压缩,支持zip、gz、bz2、xz;
例(理解copytree源码中ignore(src,names),重要技巧):
def ignore(src,names):
return set(filter(lambda x:x.startswith('t'),names))
同
lambda src,names:set(filter(lambda x:x.startswith('t'),names))
def fn(x,file_names):
return set(filter(lambda x:x.startswith('t'),file_names))
同
lambda x,file_names:set(filter(lambda x:x.startswith('t'),file_names))
注:
重要内建函数:
filter(),过滤;
sorted();
map()或zip(),每个元素都动;
In [24]: zip(range(5),(1,)*len(range(5)))
Out[24]:
In [25]: for item in zip(range(5),(1,)*len(range(5))):
...: print(item)
...:
...:
(0, 1)
(1, 1)
(2, 1)
(3, 1)
(4, 1)
In [26]: map(lambda x:(x,1),range(5))
Out[26]:
In [27]: for item in map(lambda x:(x,1),range(5)):
...: print(item)
...:
(0, 1)
(1, 1)
(2, 1)
(3, 1)
(4, 1)
例:
In [18]: Path('test.txt').write_text('abcde')
Out[18]: 5
In [19]: Path('test.txt').read_text()
Out[19]: 'abcde'
In [20]: with open('test.txt') as f1:
...: with open('test_copy.txt','w') as f2:
...: shutil.copyfileobj(f1,f2)
...:
In [21]: Path('test_copy.txt').read_text()
Out[21]: 'abcde'
In [22]: with open('test.txt','r+') as f1: #错误,写完后文件指针在EOF,f2复制的内容为空,一般不在代码中写入
...: f1.write('abcd\n1234')
...: f1.flush()
...: with open('test_copy.txt','w') as f2:
...: shutil.copyfileobj(f1,f2)
...:
In [23]: Path('test_copy.txt').read_text()
Out[23]: ''
In [3]: shutil.make_archive(r'c:\webproject\mysite\test','gztar','.') #压缩文件名、压缩格式(bztar|gztar|tar|zip)、压缩目录
Out[3]: 'c:\\webproject\\mysite\\test.tar.gz'
In [8]: shutil.unpack_archive(r'c:\webproject\mysite\test.tar.gz','e:\\test\\') #解压
In [10]: with tarfile.open('test.tar.gz',mode='r:gz') as tf: #tarfile.open()返回一个tarfile对象;mode指定压缩算法,’r:gz’或’r:bz2’,’w:gz’或’w:bz2’
...: for member in tf.getmembers(): #获取tar包中的文件列表
...: print(member)
...:
……
In [22]: with tarfile.open(r'c:\webproject\mysite\test.tar.gz',mode='w:gz') as tf:
...: tf.add('c:/webproject/mysite') #打包
In [26]: with tarfile.open('e:/test/test.tar.gz','r:gz') as tf:
...: tf.extractall('e:/test/') #解压,extractall解压所有文件,extract解压单个文件
In [28]: import zipfile
In [37]: with zipfile.ZipFile('c:/webproject/mysite/tset.zip','w') as tf:
...: tf.write('c:/webproject/mysite/db.sqlite3')
In [41]: shutil.copy2('c:/webproject/mysite/tset.zip','e:/test/')
Out[41]: 'e:/test/tset.zip'
In [42]: with zipfile.ZipFile('e:/test/tset.zip','r') as tf:
...: print(tf.namelist())
...:
['webproject/mysite/db.sqlite3']
In [45]: with zipfile.ZipFile('e:/test/tset.zip','r') as tf:
...: tf.extractall('e:/test/')
...: