模块,用一砣代码实现了某个功能的代码集合。

参考资源:http://www.cnblogs.com/alex3714/articles/5161349.html

类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合。而对于一个复杂的功能来,可能需要多个函数才能完成(函数又可以在不同的.py文件中),n个 .py 文件组成的代码集合就称为模块。

如:os 是系统相关的模块;file是文件操作相关的模块

模块分为三种:

  • 自定义模块
  • 内置模块
  • 开源模块

自定义模块

1、定义模块

情景一:

  

情景二:

  

情景三:

  

2、导入模块

Python之所以应用越来越广泛,在一定程度上也依赖于其为程序员提供了大量的模块以供使用,如果想要使用模块,则需要导入。导入模块有一下几种方法:

1
2
3
4
import module
from module.xx.xx import xx
from module.xx.xx import xx as rename  
from module.xx.xx import *

导入模块其实就是告诉Python解释器去解释那个py文件

  • 导入一个py文件,解释器解释该py文件
  • 导入一个包,解释器解释该包下的 __init__.py 文件

那么问题来了,导入模块时是根据那个路径作为基准来进行的呢?即:sys.path

1
2
3
4
5
import sys
print sys.path
  
结果:
['/Users/wupeiqi/PycharmProjects/calculator/p1/pp1''/usr/local/lib/python2.7/site-packages/setuptools-15.2-py2.7.egg''/usr/local/lib/python2.7/site-packages/distribute-0.6.28-py2.7.egg''/usr/local/lib/python2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.10-x86_64.egg''/usr/local/lib/python2.7/site-packages/xlutils-1.7.1-py2.7.egg''/usr/local/lib/python2.7/site-packages/xlwt-1.0.0-py2.7.egg''/usr/local/lib/python2.7/site-packages/xlrd-0.9.3-py2.7.egg''/usr/local/lib/python2.7/site-packages/tornado-4.1-py2.7-macosx-10.10-x86_64.egg''/usr/local/lib/python2.7/site-packages/backports.ssl_match_hostname-3.4.0.2-py2.7.egg''/usr/local/lib/python2.7/site-packages/certifi-2015.4.28-py2.7.egg''/usr/local/lib/python2.7/site-packages/pyOpenSSL-0.15.1-py2.7.egg''/usr/local/lib/python2.7/site-packages/six-1.9.0-py2.7.egg''/usr/local/lib/python2.7/site-packages/cryptography-0.9.1-py2.7-macosx-10.10-x86_64.egg''/usr/local/lib/python2.7/site-packages/cffi-1.1.1-py2.7-macosx-10.10-x86_64.egg''/usr/local/lib/python2.7/site-packages/ipaddress-1.0.7-py2.7.egg''/usr/local/lib/python2.7/site-packages/enum34-1.0.4-py2.7.egg''/usr/local/lib/python2.7/site-packages/pyasn1-0.1.7-py2.7.egg''/usr/local/lib/python2.7/site-packages/idna-2.0-py2.7.egg''/usr/local/lib/python2.7/site-packages/pycparser-2.13-py2.7.egg''/usr/local/lib/python2.7/site-packages/Django-1.7.8-py2.7.egg''/usr/local/lib/python2.7/site-packages/paramiko-1.10.1-py2.7.egg''/usr/local/lib/python2.7/site-packages/gevent-1.0.2-py2.7-macosx-10.10-x86_64.egg''/usr/local/lib/python2.7/site-packages/greenlet-0.4.7-py2.7-macosx-10.10-x86_64.egg''/Users/wupeiqi/PycharmProjects/calculator''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python27.zip''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old''/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload''/usr/local/lib/python2.7/site-packages''/Library/Python/2.7/site-packages']

如果sys.path路径列表没有你想要的路径,可以通过 sys.path.append('路径') 添加。
通过os模块可以获取各种目录,例如:

  1. import sys
  2. import os
  3.  
  4. pre_path = os.path.abspath('../')
  5. sys.path.append(pre_path)

开源模块

一、下载安装

下载安装有两种方式:

  1. yum
  2. pip
  3. apt-get
  4. ...
  5. 下载源码
  6. 解压源码
  7. 进入目录
  8. 编译源码 python setup.py build
  9. 安装源码 python setup.py install

注:在使用源码安装时,需要使用到gcc编译和python开发环境,所以,需要先执行:

1
2
3
4
yum install gcc
yum install python-devel
apt-get python-dev

安装成功后,模块会自动安装到 sys.path 中的某个目录中,如:

1
/usr/lib/python2.7/site-packages/

二、导入模块

同自定义模块中导入的方式

三、模块 paramiko

paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。

1、下载安装

1
pip3 install paramiko

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
 
# 下载安装 pycrypto
wget http://files.cnblogs.com/files/wupeiqi/pycrypto-2.6.1.tar.gz
tar -xvf pycrypto-2.6.1.tar.gz
cd pycrypto-2.6.1
python setup.py build
python setup.py install
 
# 进入python环境,导入Crypto检查是否安装成功
 
# 下载安装 paramiko
wget http://files.cnblogs.com/files/wupeiqi/paramiko-1.10.1.tar.gz
tar -xvf paramiko-1.10.1.tar.gz
cd paramiko-1.10.1
python setup.py build
python setup.py install
 
# 进入python环境,导入paramiko检查是否安装成功

2、使用模块

  1. #!/usr/bin/env python
  2. #coding:utf-8
  3.  
  4. import paramiko
  5.  
  6. ssh = paramiko.SSHClient()
  7. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  8. ssh.connect('192.168.1.108', 22, 'alex', '123')
  9. stdin, stdout, stderr = ssh.exec_command('df')
  10. print stdout.read()
  11. ssh.close();
  12.  
  13. 执行命令 - 通过用户名和密码连接服务器

  

  1. import paramiko
  2.  
  3. private_key_path = '/home/auto/.ssh/id_rsa'
  4. key = paramiko.RSAKey.from_private_key_file(private_key_path)
  5.  
  6. ssh = paramiko.SSHClient()
  7. ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
  8. ssh.connect('主机名 ', 端口, '用户名', key)
  9.  
  10. stdin, stdout, stderr = ssh.exec_command('df')
  11. print stdout.read()
  12. ssh.close()
  13.  
  14. 执行命令 - 过密钥链接服务器

  

  1. import os,sys
  2. import paramiko
  3.  
  4. t = paramiko.Transport(('182.92.219.86',22))
  5. t.connect(username='wupeiqi',password='123')
  6. sftp = paramiko.SFTPClient.from_transport(t)
  7. sftp.put('/tmp/test.py','/tmp/test.py')
  8. t.close()
  9.  
  10. import os,sys
  11. import paramiko
  12.  
  13. t = paramiko.Transport(('182.92.219.86',22))
  14. t.connect(username='wupeiqi',password='123')
  15. sftp = paramiko.SFTPClient.from_transport(t)
  16. sftp.get('/tmp/test.py','/tmp/test2.py')
  17. t.close()
  18.  
  19. 上传或者下载文件 - 通过用户名和密码

  

  1. import paramiko
  2.  
  3. pravie_key_path = '/home/auto/.ssh/id_rsa'
  4. key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
  5.  
  6. t = paramiko.Transport(('182.92.219.86',22))
  7. t.connect(username='wupeiqi',pkey=key)
  8.  
  9. sftp = paramiko.SFTPClient.from_transport(t)
  10. sftp.put('/tmp/test3.py','/tmp/test3.py')
  11.  
  12. t.close()
  13.  
  14. import paramiko
  15.  
  16. pravie_key_path = '/home/auto/.ssh/id_rsa'
  17. key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
  18.  
  19. t = paramiko.Transport(('182.92.219.86',22))
  20. t.connect(username='wupeiqi',pkey=key)
  21.  
  22. sftp = paramiko.SFTPClient.from_transport(t)
  23. sftp.get('/tmp/test3.py','/tmp/test4.py')
  24.  
  25. t.close()
  26.  
  27. 上传或下载文件 - 通过密钥

内置模块

一、os

用于提供系统级别的操作

  1. os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
  2. os.chdir("dirname") 改变当前脚本工作目录;相当于shellcd
  3. os.curdir 返回当前目录: ('.')
  4. os.pardir 获取当前目录的父目录字符串名:('..')
  5. os.makedirs('dirname1/dirname2') 可生成多层递归目录
  6. os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
  7. os.mkdir('dirname') 生成单级目录;相当于shellmkdir dirname
  8. os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shellrmdir dirname
  9. os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
  10. os.remove() 删除一个文件
  11. os.rename("oldname","newname") 重命名文件/目录
  12. os.stat('path/filename') 获取文件/目录信息
  13. os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
  14. os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
  15. os.pathsep 输出用于分割文件路径的字符串
  16. os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
  17. os.system("bash command") 运行shell命令,直接显示
  18. os.environ 获取系统环境变量
  19. os.path.abspath(path) 返回path规范化的绝对路径
  20. os.path.split(path) path分割成目录和文件名二元组返回
  21. os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
  22. os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
  23. os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
  24. os.path.isabs(path) 如果path是绝对路径,返回True
  25. os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
  26. os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
  27. os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
  28. os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
  29. os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

更多猛击这里

二、sys

用于提供对解释器相关的操作

  1. sys.argv 命令行参数List,第一个元素是程序本身路径
  2. sys.exit(n) 退出程序,正常退出时exit(0)
  3. sys.version 获取Python解释程序的版本信息
  4. sys.maxint 最大的Int
  5. sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
  6. sys.platform 返回操作系统平台名称
  7. sys.stdout.write('please:')
  8. val = sys.stdin.readline()[:-1]

更多猛击这里

三、hashlib 

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

  1. import md5
  2. hash = md5.new()
  3. hash.update('admin')
  4. print hash.hexdigest()
  1. import sha
  2.  
  3. hash = sha.new()
  4. hash.update('admin')
  5. print hash.hexdigest()

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import hashlib
 
# ######## md5 ########
 
hash = hashlib.md5()
hash.update('admin')
print hash.hexdigest()
 
# ######## sha1 ########
 
hash = hashlib.sha1()
hash.update('admin')
print hash.hexdigest()
 
# ######## sha256 ########
 
hash = hashlib.sha256()
hash.update('admin')
print hash.hexdigest()
 
 
# ######## sha384 ########
 
hash = hashlib.sha384()
hash.update('admin')
print hash.hexdigest()
 
# ######## sha512 ########
 
hash = hashlib.sha512()
hash.update('admin')
print hash.hexdigest()

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

1
2
3
4
5
6
7
import hashlib
 
# ######## md5 ########
 
hash = hashlib.md5('898oaFs09f')
hash.update('admin')
print hash.hexdigest()

还不够吊?python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密

1
2
3
4
import hmac
= hmac.new('wueiqi')
h.update('hellowo')
print h.hexdigest()

不能再牛逼了!!!

四、json 和 pickle 

用于序列化的两个模块

  • json,用于字符串 和 python数据类型间进行转换
  • pickle,用于python特有的类型 和 python的数据类型间进行转换

Json模块提供了四个功能:dumps、dump、loads、load

pickle模块提供了四个功能:dumps、dump、loads、load

五、执行系统命令 

可以执行shell命令的相关模块和函数有:

  • os.system
  • os.spawn*
  • os.popen*          --废弃
  • popen2.*           --废弃
  • commands.*      --废弃,3.x中被移除
  1. import commands
  2.  
  3. result = commands.getoutput('cmd')
  4. result = commands.getstatus('cmd')
  5. result = commands.getstatusoutput('cmd')

以上执行shell命令的相关的模块和函数的功能均在 subprocess 模块中实现,并提供了更丰富的功能。

call 

执行命令,返回状态码

1
2
ret = subprocess.call(["ls""-l"], shell=False)
ret = subprocess.call("ls -l", shell=True)

shell = True ,允许 shell 命令是字符串形式

check_call

执行命令,如果执行状态码是 0 ,则返回0,否则抛异常

1
2
subprocess.check_call(["ls""-l"])
subprocess.check_call("exit 1", shell=True)

check_output

执行命令,如果状态码是 0 ,则返回执行结果,否则抛异常

1
2
subprocess.check_output(["echo""Hello World!"])
subprocess.check_output("exit 1", shell=True)

subprocess.Popen(...)

用于执行复杂的系统命令

参数:

  • args:shell命令,可以是字符串或者序列类型(如:list,元组)
  • bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
  • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
  • preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
  • close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
    所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
  • shell:同上
  • cwd:用于设置子进程的当前目录
  • env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
  • universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
  • startupinfo与createionflags只在windows下有效
    将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
  1. import subprocess
  2. ret1 = subprocess.Popen(["mkdir","t1"])
  3. ret2 = subprocess.Popen("mkdir t2", shell=True)

终端输入的命令分为两种:

  • 输入即可得到输出,如:ifconfig
  • 输入进行某环境,依赖再输入,如:python
  1. import subprocess
  2.  
  3. obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)
  4.  
  5. 复制代码
  6. import subprocess
  7.  
  8. obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  9. obj.stdin.write('print 1 \n ')
  10. obj.stdin.write('print 2 \n ')
  11. obj.stdin.write('print 3 \n ')
  12. obj.stdin.write('print 4 \n ')
  13. obj.stdin.close()
  14.  
  15. cmd_out = obj.stdout.read()
  16. obj.stdout.close()
  17. cmd_error = obj.stderr.read()
  18. obj.stderr.close()
  19.  
  20. print cmd_out
  21. print cmd_error
  22. 复制代码
  23.  
  24. 复制代码
  25. import subprocess
  26.  
  27. obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  28. obj.stdin.write('print 1 \n ')
  29. obj.stdin.write('print 2 \n ')
  30. obj.stdin.write('print 3 \n ')
  31. obj.stdin.write('print 4 \n ')
  32.  
  33. out_error_list = obj.communicate()
  34. print out_error_list
  35. 复制代码
  36.  
  37. import subprocess
  38.  
  39. obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  40. out_error_list = obj.communicate('print "hello"')
  41. print out_error_list

更多猛击这里

六、shutil

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

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

  1. def copyfileobj(fsrc, fdst, length=16*1024):
  2. """copy data from file-like object fsrc to file-like object fdst"""
  3. while 1:
  4. buf = fsrc.read(length)
  5. if not buf:
  6. break
  7. fdst.write(buf)

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

  1. def copyfile(src, dst):
  2. """Copy data from src to dst"""
  3. if _samefile(src, dst):
  4. raise Error("`%s` and `%s` are the same file" % (src, dst))
  5.  
  6. for fn in [src, dst]:
  7. try:
  8. st = os.stat(fn)
  9. except OSError:
  10. # File most likely does not exist
  11. pass
  12. else:
  13. # XXX What about other special files? (sockets, devices...)
  14. if stat.S_ISFIFO(st.st_mode):
  15. raise SpecialFileError("`%s` is a named pipe" % fn)
  16.  
  17. with open(src, 'rb') as fsrc:
  18. with open(dst, 'wb') as fdst:
  19. copyfileobj(fsrc, fdst)

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

  1. def copymode(src, dst):
  2. """Copy mode bits from src to dst"""
  3. if hasattr(os, 'chmod'):
  4. st = os.stat(src)
  5. mode = stat.S_IMODE(st.st_mode)
  6. os.chmod(dst, mode)

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

  1. def copystat(src, dst):
  2. """Copy all stat info (mode bits, atime, mtime, flags) from src to dst"""
  3. st = os.stat(src)
  4. mode = stat.S_IMODE(st.st_mode)
  5. if hasattr(os, 'utime'):
  6. os.utime(dst, (st.st_atime, st.st_mtime))
  7. if hasattr(os, 'chmod'):
  8. os.chmod(dst, mode)
  9. if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
  10. try:
  11. os.chflags(dst, st.st_flags)
  12. except OSError, why:
  13. for err in 'EOPNOTSUPP', 'ENOTSUP':
  14. if hasattr(errno, err) and why.errno == getattr(errno, err):
  15. break
  16. else:
  17. raise

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

  1. def copy(src, dst):
  2. """Copy data and mode bits ("cp src dst").
  3.  
  4. The destination may be a directory.
  5.  
  6. """
  7. if os.path.isdir(dst):
  8. dst = os.path.join(dst, os.path.basename(src))
  9. copyfile(src, dst)
  10. copymode(src, dst)

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

  1. def copy2(src, dst):
  2. """Copy data and all stat info ("cp -p src dst").
  3.  
  4. The destination may be a directory.
  5.  
  6. """
  7. if os.path.isdir(dst):
  8. dst = os.path.join(dst, os.path.basename(src))
  9. copyfile(src, dst)
  10. copystat(src, dst)

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

例如:copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

  1. def ignore_patterns(*patterns):
  2. """Function that can be used as copytree() ignore parameter.
  3.  
  4. Patterns is a sequence of glob-style patterns
  5. that are used to exclude files"""
  6. def _ignore_patterns(path, names):
  7. ignored_names = []
  8. for pattern in patterns:
  9. ignored_names.extend(fnmatch.filter(names, pattern))
  10. return set(ignored_names)
  11. return _ignore_patterns
  12.  
  13. def copytree(src, dst, symlinks=False, ignore=None):
  14. """Recursively copy a directory tree using copy2().
  15.  
  16. The destination directory must not already exist.
  17. If exception(s) occur, an Error is raised with a list of reasons.
  18.  
  19. If the optional symlinks flag is true, symbolic links in the
  20. source tree result in symbolic links in the destination tree; if
  21. it is false, the contents of the files pointed to by symbolic
  22. links are copied.
  23.  
  24. The optional ignore argument is a callable. If given, it
  25. is called with the `src` parameter, which is the directory
  26. being visited by copytree(), and `names` which is the list of
  27. `src` contents, as returned by os.listdir():
  28.  
  29. callable(src, names) -> ignored_names
  30.  
  31. Since copytree() is called recursively, the callable will be
  32. called once for each directory that is copied. It returns a
  33. list of names relative to the `src` directory that should
  34. not be copied.
  35.  
  36. XXX Consider this example code rather than the ultimate tool.
  37.  
  38. """
  39. names = os.listdir(src)
  40. if ignore is not None:
  41. ignored_names = ignore(src, names)
  42. else:
  43. ignored_names = set()
  44.  
  45. os.makedirs(dst)
  46. errors = []
  47. for name in names:
  48. if name in ignored_names:
  49. continue
  50. srcname = os.path.join(src, name)
  51. dstname = os.path.join(dst, name)
  52. try:
  53. if symlinks and os.path.islink(srcname):
  54. linkto = os.readlink(srcname)
  55. os.symlink(linkto, dstname)
  56. elif os.path.isdir(srcname):
  57. copytree(srcname, dstname, symlinks, ignore)
  58. else:
  59. # Will raise a SpecialFileError for unsupported file types
  60. copy2(srcname, dstname)
  61. # catch the Error from the recursive copytree so that we can
  62. # continue with other files
  63. except Error, err:
  64. errors.extend(err.args[0])
  65. except EnvironmentError, why:
  66. errors.append((srcname, dstname, str(why)))
  67. try:
  68. copystat(src, dst)
  69. except OSError, why:
  70. if WindowsError is not None and isinstance(why, WindowsError):
  71. # Copying file access times may fail on Windows
  72. pass
  73. else:
  74. errors.append((src, dst, str(why)))
  75. if errors:
  76. raise Error, errors

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

  1. def rmtree(path, ignore_errors=False, onerror=None):
  2. """Recursively delete a directory tree.
  3.  
  4. If ignore_errors is set, errors are ignored; otherwise, if onerror
  5. is set, it is called to handle the error with arguments (func,
  6. path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
  7. path is the argument to that function that caused it to fail; and
  8. exc_info is a tuple returned by sys.exc_info(). If ignore_errors
  9. is false and onerror is None, an exception is raised.
  10.  
  11. """
  12. if ignore_errors:
  13. def onerror(*args):
  14. pass
  15. elif onerror is None:
  16. def onerror(*args):
  17. raise
  18. try:
  19. if os.path.islink(path):
  20. # symlinks to directories are forbidden, see bug #1669
  21. raise OSError("Cannot call rmtree on a symbolic link")
  22. except OSError:
  23. onerror(os.path.islink, path, sys.exc_info())
  24. # can't continue even if onerror hook returns
  25. return
  26. names = []
  27. try:
  28. names = os.listdir(path)
  29. except os.error, err:
  30. onerror(os.listdir, path, sys.exc_info())
  31. for name in names:
  32. fullname = os.path.join(path, name)
  33. try:
  34. mode = os.lstat(fullname).st_mode
  35. except os.error:
  36. mode = 0
  37. if stat.S_ISDIR(mode):
  38. rmtree(fullname, ignore_errors, onerror)
  39. else:
  40. try:
  41. os.remove(fullname)
  42. except os.error, err:
  43. onerror(os.remove, fullname, sys.exc_info())
  44. try:
  45. os.rmdir(path)
  46. except os.error:
  47. onerror(os.rmdir, path, sys.exc_info())

shutil.move(src, dst)
递归的去移动文件

  1. def move(src, dst):
  2. """Recursively move a file or directory to another location. This is
  3. similar to the Unix "mv" command.
  4.  
  5. If the destination is a directory or a symlink to a directory, the source
  6. is moved inside the directory. The destination path must not already
  7. exist.
  8.  
  9. If the destination already exists but is not a directory, it may be
  10. overwritten depending on os.rename() semantics.
  11.  
  12. If the destination is on our current filesystem, then rename() is used.
  13. Otherwise, src is copied to the destination and then removed.
  14. A lot more could be done here... A look at a mv.c shows a lot of
  15. the issues this implementation glosses over.
  16.  
  17. """
  18. real_dst = dst
  19. if os.path.isdir(dst):
  20. if _samefile(src, dst):
  21. # We might be on a case insensitive filesystem,
  22. # perform the rename anyway.
  23. os.rename(src, dst)
  24. return
  25.  
  26. real_dst = os.path.join(dst, _basename(src))
  27. if os.path.exists(real_dst):
  28. raise Error, "Destination path '%s' already exists" % real_dst
  29. try:
  30. os.rename(src, real_dst)
  31. except OSError:
  32. if os.path.isdir(src):
  33. if _destinsrc(src, dst):
  34. raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
  35. copytree(src, real_dst, symlinks=True)
  36. rmtree(src)
  37. else:
  38. copy2(src, real_dst)
  39. os.unlink(src)

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

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

  • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
    如:www                        =>保存至当前路径
    如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
  • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
  • root_dir: 要压缩的文件夹路径(默认当前目录)
  • owner: 用户,默认当前用户
  • group: 组,默认当前组
  • logger: 用于记录日志,通常是logging.Logger对象
1
2
3
4
5
6
7
8
9
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录
 
import shutil
ret = shutil.make_archive("wwwwwwwwww"'gztar', root_dir='/Users/wupeiqi/Downloads/test')
 
 
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录
import shutil
ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww"'gztar', root_dir='/Users/wupeiqi/Downloads/test')
  1. def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
  2. dry_run=0, owner=None, group=None, logger=None):
  3. """Create an archive file (eg. zip or tar).
  4.  
  5. 'base_name' is the name of the file to create, minus any format-specific
  6. extension; 'format' is the archive format: one of "zip", "tar", "bztar"
  7. or "gztar".
  8.  
  9. 'root_dir' is a directory that will be the root directory of the
  10. archive; ie. we typically chdir into 'root_dir' before creating the
  11. archive. 'base_dir' is the directory where we start archiving from;
  12. ie. 'base_dir' will be the common prefix of all files and
  13. directories in the archive. 'root_dir' and 'base_dir' both default
  14. to the current directory. Returns the name of the archive file.
  15.  
  16. 'owner' and 'group' are used when creating a tar archive. By default,
  17. uses the current owner and group.
  18. """
  19. save_cwd = os.getcwd()
  20. if root_dir is not None:
  21. if logger is not None:
  22. logger.debug("changing into '%s'", root_dir)
  23. base_name = os.path.abspath(base_name)
  24. if not dry_run:
  25. os.chdir(root_dir)
  26.  
  27. if base_dir is None:
  28. base_dir = os.curdir
  29.  
  30. kwargs = {'dry_run': dry_run, 'logger': logger}
  31.  
  32. try:
  33. format_info = _ARCHIVE_FORMATS[format]
  34. except KeyError:
  35. raise ValueError, "unknown archive format '%s'" % format
  36.  
  37. func = format_info[0]
  38. for arg, val in format_info[1]:
  39. kwargs[arg] = val
  40.  
  41. if format != 'zip':
  42. kwargs['owner'] = owner
  43. kwargs['group'] = group
  44.  
  45. try:
  46. filename = func(base_name, base_dir, **kwargs)
  47. finally:
  48. if root_dir is not None:
  49. if logger is not None:
  50. logger.debug("changing back to '%s'", save_cwd)
  51. os.chdir(save_cwd)
  52.  
  53. return filename

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

  1. import zipfile
  2.  
  3. # 压缩
  4. z = zipfile.ZipFile('laxi.zip', 'w')
  5. z.write('a.log')
  6. z.write('data.data')
  7. z.close()
  8.  
  9. # 解压
  10. z = zipfile.ZipFile('laxi.zip', 'r')
  11. z.extractall()
  12. z.close()
  13. 复制代码
  14.  
  15. 复制代码
  16. import tarfile
  17.  
  18. # 压缩
  19. tar = tarfile.open('your.tar','w')
  20. tar.add('/Users/wupeiqi/PycharmProjects/bbs2.zip', arcname='bbs2.zip')
  21. tar.add('/Users/wupeiqi/PycharmProjects/cmdb.zip', arcname='cmdb.zip')
  22. tar.close()
  23.  
  24. # 解压
  25. tar = tarfile.open('your.tar','r')
  26. tar.extractall() # 可设置解压地址
  27. tar.close()
  28. 复制代码
  29.  
  30. 复制代码
  31. class ZipFile(object):
  32. """ Class with methods to open, read, write, close, list zip files.
  33.  
  34. z = ZipFile(file, mode="r", compression=ZIP_STORED, allowZip64=False)
  35.  
  36. file: Either the path to the file, or a file-like object.
  37. If it is a path, the file will be opened and closed by ZipFile.
  38. mode: The mode can be either read "r", write "w" or append "a".
  39. compression: ZIP_STORED (no compression) or ZIP_DEFLATED (requires zlib).
  40. allowZip64: if True ZipFile will create files with ZIP64 extensions when
  41. needed, otherwise it will raise an exception when this would
  42. be necessary.
  43.  
  44. """
  45.  
  46. fp = None # Set here since __del__ checks it
  47.  
  48. def __init__(self, file, mode="r", compression=ZIP_STORED, allowZip64=False):
  49. """Open the ZIP file with mode read "r", write "w" or append "a"."""
  50. if mode not in ("r", "w", "a"):
  51. raise RuntimeError('ZipFile() requires mode "r", "w", or "a"')
  52.  
  53. if compression == ZIP_STORED:
  54. pass
  55. elif compression == ZIP_DEFLATED:
  56. if not zlib:
  57. raise RuntimeError,\
  58. "Compression requires the (missing) zlib module"
  59. else:
  60. raise RuntimeError, "That compression method is not supported"
  61.  
  62. self._allowZip64 = allowZip64
  63. self._didModify = False
  64. self.debug = 0 # Level of printing: 0 through 3
  65. self.NameToInfo = {} # Find file info given name
  66. self.filelist = [] # List of ZipInfo instances for archive
  67. self.compression = compression # Method of compression
  68. self.mode = key = mode.replace('b', '')[0]
  69. self.pwd = None
  70. self._comment = ''
  71.  
  72. # Check if we were passed a file-like object
  73. if isinstance(file, basestring):
  74. self._filePassed = 0
  75. self.filename = file
  76. modeDict = {'r' : 'rb', 'w': 'wb', 'a' : 'r+b'}
  77. try:
  78. self.fp = open(file, modeDict[mode])
  79. except IOError:
  80. if mode == 'a':
  81. mode = key = 'w'
  82. self.fp = open(file, modeDict[mode])
  83. else:
  84. raise
  85. else:
  86. self._filePassed = 1
  87. self.fp = file
  88. self.filename = getattr(file, 'name', None)
  89.  
  90. try:
  91. if key == 'r':
  92. self._RealGetContents()
  93. elif key == 'w':
  94. # set the modified flag so central directory gets written
  95. # even if no files are added to the archive
  96. self._didModify = True
  97. elif key == 'a':
  98. try:
  99. # See if file is a zip file
  100. self._RealGetContents()
  101. # seek to start of directory and overwrite
  102. self.fp.seek(self.start_dir, 0)
  103. except BadZipfile:
  104. # file is not a zip file, just append
  105. self.fp.seek(0, 2)
  106.  
  107. # set the modified flag so central directory gets written
  108. # even if no files are added to the archive
  109. self._didModify = True
  110. else:
  111. raise RuntimeError('Mode must be "r", "w" or "a"')
  112. except:
  113. fp = self.fp
  114. self.fp = None
  115. if not self._filePassed:
  116. fp.close()
  117. raise
  118.  
  119. def __enter__(self):
  120. return self
  121.  
  122. def __exit__(self, type, value, traceback):
  123. self.close()
  124.  
  125. def _RealGetContents(self):
  126. """Read in the table of contents for the ZIP file."""
  127. fp = self.fp
  128. try:
  129. endrec = _EndRecData(fp)
  130. except IOError:
  131. raise BadZipfile("File is not a zip file")
  132. if not endrec:
  133. raise BadZipfile, "File is not a zip file"
  134. if self.debug > 1:
  135. print endrec
  136. size_cd = endrec[_ECD_SIZE] # bytes in central directory
  137. offset_cd = endrec[_ECD_OFFSET] # offset of central directory
  138. self._comment = endrec[_ECD_COMMENT] # archive comment
  139.  
  140. # "concat" is zero, unless zip was concatenated to another file
  141. concat = endrec[_ECD_LOCATION] - size_cd - offset_cd
  142. if endrec[_ECD_SIGNATURE] == stringEndArchive64:
  143. # If Zip64 extension structures are present, account for them
  144. concat -= (sizeEndCentDir64 + sizeEndCentDir64Locator)
  145.  
  146. if self.debug > 2:
  147. inferred = concat + offset_cd
  148. print "given, inferred, offset", offset_cd, inferred, concat
  149. # self.start_dir: Position of start of central directory
  150. self.start_dir = offset_cd + concat
  151. fp.seek(self.start_dir, 0)
  152. data = fp.read(size_cd)
  153. fp = cStringIO.StringIO(data)
  154. total = 0
  155. while total < size_cd:
  156. centdir = fp.read(sizeCentralDir)
  157. if len(centdir) != sizeCentralDir:
  158. raise BadZipfile("Truncated central directory")
  159. centdir = struct.unpack(structCentralDir, centdir)
  160. if centdir[_CD_SIGNATURE] != stringCentralDir:
  161. raise BadZipfile("Bad magic number for central directory")
  162. if self.debug > 2:
  163. print centdir
  164. filename = fp.read(centdir[_CD_FILENAME_LENGTH])
  165. # Create ZipInfo instance to store file information
  166. x = ZipInfo(filename)
  167. x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH])
  168. x.comment = fp.read(centdir[_CD_COMMENT_LENGTH])
  169. x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET]
  170. (x.create_version, x.create_system, x.extract_version, x.reserved,
  171. x.flag_bits, x.compress_type, t, d,
  172. x.CRC, x.compress_size, x.file_size) = centdir[1:12]
  173. x.volume, x.internal_attr, x.external_attr = centdir[15:18]
  174. # Convert date/time code to (year, month, day, hour, min, sec)
  175. x._raw_time = t
  176. x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F,
  177. t>>11, (t>>5)&0x3F, (t&0x1F) * 2 )
  178.  
  179. x._decodeExtra()
  180. x.header_offset = x.header_offset + concat
  181. x.filename = x._decodeFilename()
  182. self.filelist.append(x)
  183. self.NameToInfo[x.filename] = x
  184.  
  185. # update total bytes read from central directory
  186. total = (total + sizeCentralDir + centdir[_CD_FILENAME_LENGTH]
  187. + centdir[_CD_EXTRA_FIELD_LENGTH]
  188. + centdir[_CD_COMMENT_LENGTH])
  189.  
  190. if self.debug > 2:
  191. print "total", total
  192.  
  193. def namelist(self):
  194. """Return a list of file names in the archive."""
  195. l = []
  196. for data in self.filelist:
  197. l.append(data.filename)
  198. return l
  199.  
  200. def infolist(self):
  201. """Return a list of class ZipInfo instances for files in the
  202. archive."""
  203. return self.filelist
  204.  
  205. def printdir(self):
  206. """Print a table of contents for the zip file."""
  207. print "%-46s %19s %12s" % ("File Name", "Modified ", "Size")
  208. for zinfo in self.filelist:
  209. date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6]
  210. print "%-46s %s %12d" % (zinfo.filename, date, zinfo.file_size)
  211.  
  212. def testzip(self):
  213. """Read all the files and check the CRC."""
  214. chunk_size = 2 ** 20
  215. for zinfo in self.filelist:
  216. try:
  217. # Read by chunks, to avoid an OverflowError or a
  218. # MemoryError with very large embedded files.
  219. with self.open(zinfo.filename, "r") as f:
  220. while f.read(chunk_size): # Check CRC-32
  221. pass
  222. except BadZipfile:
  223. return zinfo.filename
  224.  
  225. def getinfo(self, name):
  226. """Return the instance of ZipInfo given 'name'."""
  227. info = self.NameToInfo.get(name)
  228. if info is None:
  229. raise KeyError(
  230. 'There is no item named %r in the archive' % name)
  231.  
  232. return info
  233.  
  234. def setpassword(self, pwd):
  235. """Set default password for encrypted files."""
  236. self.pwd = pwd
  237.  
  238. @property
  239. def comment(self):
  240. """The comment text associated with the ZIP file."""
  241. return self._comment
  242.  
  243. @comment.setter
  244. def comment(self, comment):
  245. # check for valid comment length
  246. if len(comment) > ZIP_MAX_COMMENT:
  247. import warnings
  248. warnings.warn('Archive comment is too long; truncating to %d bytes'
  249. % ZIP_MAX_COMMENT, stacklevel=2)
  250. comment = comment[:ZIP_MAX_COMMENT]
  251. self._comment = comment
  252. self._didModify = True
  253.  
  254. def read(self, name, pwd=None):
  255. """Return file bytes (as a string) for name."""
  256. return self.open(name, "r", pwd).read()
  257.  
  258. def open(self, name, mode="r", pwd=None):
  259. """Return file-like object for 'name'."""
  260. if mode not in ("r", "U", "rU"):
  261. raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
  262. if not self.fp:
  263. raise RuntimeError, \
  264. "Attempt to read ZIP archive that was already closed"
  265.  
  266. # Only open a new file for instances where we were not
  267. # given a file object in the constructor
  268. if self._filePassed:
  269. zef_file = self.fp
  270. should_close = False
  271. else:
  272. zef_file = open(self.filename, 'rb')
  273. should_close = True
  274.  
  275. try:
  276. # Make sure we have an info object
  277. if isinstance(name, ZipInfo):
  278. # 'name' is already an info object
  279. zinfo = name
  280. else:
  281. # Get info object for name
  282. zinfo = self.getinfo(name)
  283.  
  284. zef_file.seek(zinfo.header_offset, 0)
  285.  
  286. # Skip the file header:
  287. fheader = zef_file.read(sizeFileHeader)
  288. if len(fheader) != sizeFileHeader:
  289. raise BadZipfile("Truncated file header")
  290. fheader = struct.unpack(structFileHeader, fheader)
  291. if fheader[_FH_SIGNATURE] != stringFileHeader:
  292. raise BadZipfile("Bad magic number for file header")
  293.  
  294. fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
  295. if fheader[_FH_EXTRA_FIELD_LENGTH]:
  296. zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
  297.  
  298. if fname != zinfo.orig_filename:
  299. raise BadZipfile, \
  300. 'File name in directory "%s" and header "%s" differ.' % (
  301. zinfo.orig_filename, fname)
  302.  
  303. # check for encrypted flag & handle password
  304. is_encrypted = zinfo.flag_bits & 0x1
  305. zd = None
  306. if is_encrypted:
  307. if not pwd:
  308. pwd = self.pwd
  309. if not pwd:
  310. raise RuntimeError, "File %s is encrypted, " \
  311. "password required for extraction" % name
  312.  
  313. zd = _ZipDecrypter(pwd)
  314. # The first 12 bytes in the cypher stream is an encryption header
  315. # used to strengthen the algorithm. The first 11 bytes are
  316. # completely random, while the 12th contains the MSB of the CRC,
  317. # or the MSB of the file time depending on the header type
  318. # and is used to check the correctness of the password.
  319. bytes = zef_file.read(12)
  320. h = map(zd, bytes[0:12])
  321. if zinfo.flag_bits & 0x8:
  322. # compare against the file type from extended local headers
  323. check_byte = (zinfo._raw_time >> 8) & 0xff
  324. else:
  325. # compare against the CRC otherwise
  326. check_byte = (zinfo.CRC >> 24) & 0xff
  327. if ord(h[11]) != check_byte:
  328. raise RuntimeError("Bad password for file", name)
  329.  
  330. return ZipExtFile(zef_file, mode, zinfo, zd,
  331. close_fileobj=should_close)
  332. except:
  333. if should_close:
  334. zef_file.close()
  335. raise
  336.  
  337. def extract(self, member, path=None, pwd=None):
  338. """Extract a member from the archive to the current working directory,
  339. using its full name. Its file information is extracted as accurately
  340. as possible. `member' may be a filename or a ZipInfo object. You can
  341. specify a different directory using `path'.
  342. """
  343. if not isinstance(member, ZipInfo):
  344. member = self.getinfo(member)
  345.  
  346. if path is None:
  347. path = os.getcwd()
  348.  
  349. return self._extract_member(member, path, pwd)
  350.  
  351. def extractall(self, path=None, members=None, pwd=None):
  352. """Extract all members from the archive to the current working
  353. directory. `path' specifies a different directory to extract to.
  354. `members' is optional and must be a subset of the list returned
  355. by namelist().
  356. """
  357. if members is None:
  358. members = self.namelist()
  359.  
  360. for zipinfo in members:
  361. self.extract(zipinfo, path, pwd)
  362.  
  363. def _extract_member(self, member, targetpath, pwd):
  364. """Extract the ZipInfo object 'member' to a physical
  365. file on the path targetpath.
  366. """
  367. # build the destination pathname, replacing
  368. # forward slashes to platform specific separators.
  369. arcname = member.filename.replace('/', os.path.sep)
  370.  
  371. if os.path.altsep:
  372. arcname = arcname.replace(os.path.altsep, os.path.sep)
  373. # interpret absolute pathname as relative, remove drive letter or
  374. # UNC path, redundant separators, "." and ".." components.
  375. arcname = os.path.splitdrive(arcname)[1]
  376. arcname = os.path.sep.join(x for x in arcname.split(os.path.sep)
  377. if x not in ('', os.path.curdir, os.path.pardir))
  378. if os.path.sep == '\\':
  379. # filter illegal characters on Windows
  380. illegal = ':<>|"?*'
  381. if isinstance(arcname, unicode):
  382. table = {ord(c): ord('_') for c in illegal}
  383. else:
  384. table = string.maketrans(illegal, '_' * len(illegal))
  385. arcname = arcname.translate(table)
  386. # remove trailing dots
  387. arcname = (x.rstrip('.') for x in arcname.split(os.path.sep))
  388. arcname = os.path.sep.join(x for x in arcname if x)
  389.  
  390. targetpath = os.path.join(targetpath, arcname)
  391. targetpath = os.path.normpath(targetpath)
  392.  
  393. # Create all upper directories if necessary.
  394. upperdirs = os.path.dirname(targetpath)
  395. if upperdirs and not os.path.exists(upperdirs):
  396. os.makedirs(upperdirs)
  397.  
  398. if member.filename[-1] == '/':
  399. if not os.path.isdir(targetpath):
  400. os.mkdir(targetpath)
  401. return targetpath
  402.  
  403. with self.open(member, pwd=pwd) as source, \
  404. file(targetpath, "wb") as target:
  405. shutil.copyfileobj(source, target)
  406.  
  407. return targetpath
  408.  
  409. def _writecheck(self, zinfo):
  410. """Check for errors before writing a file to the archive."""
  411. if zinfo.filename in self.NameToInfo:
  412. import warnings
  413. warnings.warn('Duplicate name: %r' % zinfo.filename, stacklevel=3)
  414. if self.mode not in ("w", "a"):
  415. raise RuntimeError, 'write() requires mode "w" or "a"'
  416. if not self.fp:
  417. raise RuntimeError, \
  418. "Attempt to write ZIP archive that was already closed"
  419. if zinfo.compress_type == ZIP_DEFLATED and not zlib:
  420. raise RuntimeError, \
  421. "Compression requires the (missing) zlib module"
  422. if zinfo.compress_type not in (ZIP_STORED, ZIP_DEFLATED):
  423. raise RuntimeError, \
  424. "That compression method is not supported"
  425. if not self._allowZip64:
  426. requires_zip64 = None
  427. if len(self.filelist) >= ZIP_FILECOUNT_LIMIT:
  428. requires_zip64 = "Files count"
  429. elif zinfo.file_size > ZIP64_LIMIT:
  430. requires_zip64 = "Filesize"
  431. elif zinfo.header_offset > ZIP64_LIMIT:
  432. requires_zip64 = "Zipfile size"
  433. if requires_zip64:
  434. raise LargeZipFile(requires_zip64 +
  435. " would require ZIP64 extensions")
  436.  
  437. def write(self, filename, arcname=None, compress_type=None):
  438. """Put the bytes from filename into the archive under the name
  439. arcname."""
  440. if not self.fp:
  441. raise RuntimeError(
  442. "Attempt to write to ZIP archive that was already closed")
  443.  
  444. st = os.stat(filename)
  445. isdir = stat.S_ISDIR(st.st_mode)
  446. mtime = time.localtime(st.st_mtime)
  447. date_time = mtime[0:6]
  448. # Create ZipInfo instance to store file information
  449. if arcname is None:
  450. arcname = filename
  451. arcname = os.path.normpath(os.path.splitdrive(arcname)[1])
  452. while arcname[0] in (os.sep, os.altsep):
  453. arcname = arcname[1:]
  454. if isdir:
  455. arcname += '/'
  456. zinfo = ZipInfo(arcname, date_time)
  457. zinfo.external_attr = (st[0] & 0xFFFF) << 16L # Unix attributes
  458. if compress_type is None:
  459. zinfo.compress_type = self.compression
  460. else:
  461. zinfo.compress_type = compress_type
  462.  
  463. zinfo.file_size = st.st_size
  464. zinfo.flag_bits = 0x00
  465. zinfo.header_offset = self.fp.tell() # Start of header bytes
  466.  
  467. self._writecheck(zinfo)
  468. self._didModify = True
  469.  
  470. if isdir:
  471. zinfo.file_size = 0
  472. zinfo.compress_size = 0
  473. zinfo.CRC = 0
  474. zinfo.external_attr |= 0x10 # MS-DOS directory flag
  475. self.filelist.append(zinfo)
  476. self.NameToInfo[zinfo.filename] = zinfo
  477. self.fp.write(zinfo.FileHeader(False))
  478. return
  479.  
  480. with open(filename, "rb") as fp:
  481. # Must overwrite CRC and sizes with correct data later
  482. zinfo.CRC = CRC = 0
  483. zinfo.compress_size = compress_size = 0
  484. # Compressed size can be larger than uncompressed size
  485. zip64 = self._allowZip64 and \
  486. zinfo.file_size * 1.05 > ZIP64_LIMIT
  487. self.fp.write(zinfo.FileHeader(zip64))
  488. if zinfo.compress_type == ZIP_DEFLATED:
  489. cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
  490. zlib.DEFLATED, -15)
  491. else:
  492. cmpr = None
  493. file_size = 0
  494. while 1:
  495. buf = fp.read(1024 * 8)
  496. if not buf:
  497. break
  498. file_size = file_size + len(buf)
  499. CRC = crc32(buf, CRC) & 0xffffffff
  500. if cmpr:
  501. buf = cmpr.compress(buf)
  502. compress_size = compress_size + len(buf)
  503. self.fp.write(buf)
  504. if cmpr:
  505. buf = cmpr.flush()
  506. compress_size = compress_size + len(buf)
  507. self.fp.write(buf)
  508. zinfo.compress_size = compress_size
  509. else:
  510. zinfo.compress_size = file_size
  511. zinfo.CRC = CRC
  512. zinfo.file_size = file_size
  513. if not zip64 and self._allowZip64:
  514. if file_size > ZIP64_LIMIT:
  515. raise RuntimeError('File size has increased during compressing')
  516. if compress_size > ZIP64_LIMIT:
  517. raise RuntimeError('Compressed size larger than uncompressed size')
  518. # Seek backwards and write file header (which will now include
  519. # correct CRC and file sizes)
  520. position = self.fp.tell() # Preserve current position in file
  521. self.fp.seek(zinfo.header_offset, 0)
  522. self.fp.write(zinfo.FileHeader(zip64))
  523. self.fp.seek(position, 0)
  524. self.filelist.append(zinfo)
  525. self.NameToInfo[zinfo.filename] = zinfo
  526.  
  527. def writestr(self, zinfo_or_arcname, bytes, compress_type=None):
  528. """Write a file into the archive. The contents is the string
  529. 'bytes'. 'zinfo_or_arcname' is either a ZipInfo instance or
  530. the name of the file in the archive."""
  531. if not isinstance(zinfo_or_arcname, ZipInfo):
  532. zinfo = ZipInfo(filename=zinfo_or_arcname,
  533. date_time=time.localtime(time.time())[:6])
  534.  
  535. zinfo.compress_type = self.compression
  536. if zinfo.filename[-1] == '/':
  537. zinfo.external_attr = 0o40775 << 16 # drwxrwxr-x
  538. zinfo.external_attr |= 0x10 # MS-DOS directory flag
  539. else:
  540. zinfo.external_attr = 0o600 << 16 # ?rw-------
  541. else:
  542. zinfo = zinfo_or_arcname
  543.  
  544. if not self.fp:
  545. raise RuntimeError(
  546. "Attempt to write to ZIP archive that was already closed")
  547.  
  548. if compress_type is not None:
  549. zinfo.compress_type = compress_type
  550.  
  551. zinfo.file_size = len(bytes) # Uncompressed size
  552. zinfo.header_offset = self.fp.tell() # Start of header bytes
  553. self._writecheck(zinfo)
  554. self._didModify = True
  555. zinfo.CRC = crc32(bytes) & 0xffffffff # CRC-32 checksum
  556. if zinfo.compress_type == ZIP_DEFLATED:
  557. co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
  558. zlib.DEFLATED, -15)
  559. bytes = co.compress(bytes) + co.flush()
  560. zinfo.compress_size = len(bytes) # Compressed size
  561. else:
  562. zinfo.compress_size = zinfo.file_size
  563. zip64 = zinfo.file_size > ZIP64_LIMIT or \
  564. zinfo.compress_size > ZIP64_LIMIT
  565. if zip64 and not self._allowZip64:
  566. raise LargeZipFile("Filesize would require ZIP64 extensions")
  567. self.fp.write(zinfo.FileHeader(zip64))
  568. self.fp.write(bytes)
  569. if zinfo.flag_bits & 0x08:
  570. # Write CRC and file sizes after the file data
  571. fmt = '<LQQ' if zip64 else '<LLL'
  572. self.fp.write(struct.pack(fmt, zinfo.CRC, zinfo.compress_size,
  573. zinfo.file_size))
  574. self.fp.flush()
  575. self.filelist.append(zinfo)
  576. self.NameToInfo[zinfo.filename] = zinfo
  577.  
  578. def __del__(self):
  579. """Call the "close()" method in case the user forgot."""
  580. self.close()
  581.  
  582. def close(self):
  583. """Close the file, and for mode "w" and "a" write the ending
  584. records."""
  585. if self.fp is None:
  586. return
  587.  
  588. try:
  589. if self.mode in ("w", "a") and self._didModify: # write ending records
  590. pos1 = self.fp.tell()
  591. for zinfo in self.filelist: # write central directory
  592. dt = zinfo.date_time
  593. dosdate = (dt[0] - 1980) << 9 | dt[1] << 5 | dt[2]
  594. dostime = dt[3] << 11 | dt[4] << 5 | (dt[5] // 2)
  595. extra = []
  596. if zinfo.file_size > ZIP64_LIMIT \
  597. or zinfo.compress_size > ZIP64_LIMIT:
  598. extra.append(zinfo.file_size)
  599. extra.append(zinfo.compress_size)
  600. file_size = 0xffffffff
  601. compress_size = 0xffffffff
  602. else:
  603. file_size = zinfo.file_size
  604. compress_size = zinfo.compress_size
  605.  
  606. if zinfo.header_offset > ZIP64_LIMIT:
  607. extra.append(zinfo.header_offset)
  608. header_offset = 0xffffffffL
  609. else:
  610. header_offset = zinfo.header_offset
  611.  
  612. extra_data = zinfo.extra
  613. if extra:
  614. # Append a ZIP64 field to the extra's
  615. extra_data = struct.pack(
  616. '<HH' + 'Q'*len(extra),
  617. 1, 8*len(extra), *extra) + extra_data
  618.  
  619. extract_version = max(45, zinfo.extract_version)
  620. create_version = max(45, zinfo.create_version)
  621. else:
  622. extract_version = zinfo.extract_version
  623. create_version = zinfo.create_version
  624.  
  625. try:
  626. filename, flag_bits = zinfo._encodeFilenameFlags()
  627. centdir = struct.pack(structCentralDir,
  628. stringCentralDir, create_version,
  629. zinfo.create_system, extract_version, zinfo.reserved,
  630. flag_bits, zinfo.compress_type, dostime, dosdate,
  631. zinfo.CRC, compress_size, file_size,
  632. len(filename), len(extra_data), len(zinfo.comment),
  633. 0, zinfo.internal_attr, zinfo.external_attr,
  634. header_offset)
  635. except DeprecationWarning:
  636. print >>sys.stderr, (structCentralDir,
  637. stringCentralDir, create_version,
  638. zinfo.create_system, extract_version, zinfo.reserved,
  639. zinfo.flag_bits, zinfo.compress_type, dostime, dosdate,
  640. zinfo.CRC, compress_size, file_size,
  641. len(zinfo.filename), len(extra_data), len(zinfo.comment),
  642. 0, zinfo.internal_attr, zinfo.external_attr,
  643. header_offset)
  644. raise
  645. self.fp.write(centdir)
  646. self.fp.write(filename)
  647. self.fp.write(extra_data)
  648. self.fp.write(zinfo.comment)
  649.  
  650. pos2 = self.fp.tell()
  651. # Write end-of-zip-archive record
  652. centDirCount = len(self.filelist)
  653. centDirSize = pos2 - pos1
  654. centDirOffset = pos1
  655. requires_zip64 = None
  656. if centDirCount > ZIP_FILECOUNT_LIMIT:
  657. requires_zip64 = "Files count"
  658. elif centDirOffset > ZIP64_LIMIT:
  659. requires_zip64 = "Central directory offset"
  660. elif centDirSize > ZIP64_LIMIT:
  661. requires_zip64 = "Central directory size"
  662. if requires_zip64:
  663. # Need to write the ZIP64 end-of-archive records
  664. if not self._allowZip64:
  665. raise LargeZipFile(requires_zip64 +
  666. " would require ZIP64 extensions")
  667. zip64endrec = struct.pack(
  668. structEndArchive64, stringEndArchive64,
  669. 44, 45, 45, 0, 0, centDirCount, centDirCount,
  670. centDirSize, centDirOffset)
  671. self.fp.write(zip64endrec)
  672.  
  673. zip64locrec = struct.pack(
  674. structEndArchive64Locator,
  675. stringEndArchive64Locator, 0, pos2, 1)
  676. self.fp.write(zip64locrec)
  677. centDirCount = min(centDirCount, 0xFFFF)
  678. centDirSize = min(centDirSize, 0xFFFFFFFF)
  679. centDirOffset = min(centDirOffset, 0xFFFFFFFF)
  680.  
  681. endrec = struct.pack(structEndArchive, stringEndArchive,
  682. 0, 0, centDirCount, centDirCount,
  683. centDirSize, centDirOffset, len(self._comment))
  684. self.fp.write(endrec)
  685. self.fp.write(self._comment)
  686. self.fp.flush()
  687. finally:
  688. fp = self.fp
  689. self.fp = None
  690. if not self._filePassed:
  691. fp.close()
  692. 复制代码
  693.  
  694. 复制代码
  695. class TarFile(object):
  696. """The TarFile Class provides an interface to tar archives.
  697. """
  698.  
  699. debug = 0 # May be set from 0 (no msgs) to 3 (all msgs)
  700.  
  701. dereference = False # If true, add content of linked file to the
  702. # tar file, else the link.
  703.  
  704. ignore_zeros = False # If true, skips empty or invalid blocks and
  705. # continues processing.
  706.  
  707. errorlevel = 1 # If 0, fatal errors only appear in debug
  708. # messages (if debug >= 0). If > 0, errors
  709. # are passed to the caller as exceptions.
  710.  
  711. format = DEFAULT_FORMAT # The format to use when creating an archive.
  712.  
  713. encoding = ENCODING # Encoding for 8-bit character strings.
  714.  
  715. errors = None # Error handler for unicode conversion.
  716.  
  717. tarinfo = TarInfo # The default TarInfo class to use.
  718.  
  719. fileobject = ExFileObject # The default ExFileObject class to use.
  720.  
  721. def __init__(self, name=None, mode="r", fileobj=None, format=None,
  722. tarinfo=None, dereference=None, ignore_zeros=None, encoding=None,
  723. errors=None, pax_headers=None, debug=None, errorlevel=None):
  724. """Open an (uncompressed) tar archive `name'. `mode' is either 'r' to
  725. read from an existing archive, 'a' to append data to an existing
  726. file or 'w' to create a new file overwriting an existing one. `mode'
  727. defaults to 'r'.
  728. If `fileobj' is given, it is used for reading or writing data. If it
  729. can be determined, `mode' is overridden by `fileobj's mode.
  730. `fileobj' is not closed, when TarFile is closed.
  731. """
  732. modes = {"r": "rb", "a": "r+b", "w": "wb"}
  733. if mode not in modes:
  734. raise ValueError("mode must be 'r', 'a' or 'w'")
  735. self.mode = mode
  736. self._mode = modes[mode]
  737.  
  738. if not fileobj:
  739. if self.mode == "a" and not os.path.exists(name):
  740. # Create nonexistent files in append mode.
  741. self.mode = "w"
  742. self._mode = "wb"
  743. fileobj = bltn_open(name, self._mode)
  744. self._extfileobj = False
  745. else:
  746. if name is None and hasattr(fileobj, "name"):
  747. name = fileobj.name
  748. if hasattr(fileobj, "mode"):
  749. self._mode = fileobj.mode
  750. self._extfileobj = True
  751. self.name = os.path.abspath(name) if name else None
  752. self.fileobj = fileobj
  753.  
  754. # Init attributes.
  755. if format is not None:
  756. self.format = format
  757. if tarinfo is not None:
  758. self.tarinfo = tarinfo
  759. if dereference is not None:
  760. self.dereference = dereference
  761. if ignore_zeros is not None:
  762. self.ignore_zeros = ignore_zeros
  763. if encoding is not None:
  764. self.encoding = encoding
  765.  
  766. if errors is not None:
  767. self.errors = errors
  768. elif mode == "r":
  769. self.errors = "utf-8"
  770. else:
  771. self.errors = "strict"
  772.  
  773. if pax_headers is not None and self.format == PAX_FORMAT:
  774. self.pax_headers = pax_headers
  775. else:
  776. self.pax_headers = {}
  777.  
  778. if debug is not None:
  779. self.debug = debug
  780. if errorlevel is not None:
  781. self.errorlevel = errorlevel
  782.  
  783. # Init datastructures.
  784. self.closed = False
  785. self.members = [] # list of members as TarInfo objects
  786. self._loaded = False # flag if all members have been read
  787. self.offset = self.fileobj.tell()
  788. # current position in the archive file
  789. self.inodes = {} # dictionary caching the inodes of
  790. # archive members already added
  791.  
  792. try:
  793. if self.mode == "r":
  794. self.firstmember = None
  795. self.firstmember = self.next()
  796.  
  797. if self.mode == "a":
  798. # Move to the end of the archive,
  799. # before the first empty block.
  800. while True:
  801. self.fileobj.seek(self.offset)
  802. try:
  803. tarinfo = self.tarinfo.fromtarfile(self)
  804. self.members.append(tarinfo)
  805. except EOFHeaderError:
  806. self.fileobj.seek(self.offset)
  807. break
  808. except HeaderError, e:
  809. raise ReadError(str(e))
  810.  
  811. if self.mode in "aw":
  812. self._loaded = True
  813.  
  814. if self.pax_headers:
  815. buf = self.tarinfo.create_pax_global_header(self.pax_headers.copy())
  816. self.fileobj.write(buf)
  817. self.offset += len(buf)
  818. except:
  819. if not self._extfileobj:
  820. self.fileobj.close()
  821. self.closed = True
  822. raise
  823.  
  824. def _getposix(self):
  825. return self.format == USTAR_FORMAT
  826. def _setposix(self, value):
  827. import warnings
  828. warnings.warn("use the format attribute instead", DeprecationWarning,
  829. 2)
  830. if value:
  831. self.format = USTAR_FORMAT
  832. else:
  833. self.format = GNU_FORMAT
  834. posix = property(_getposix, _setposix)
  835.  
  836. #--------------------------------------------------------------------------
  837. # Below are the classmethods which act as alternate constructors to the
  838. # TarFile class. The open() method is the only one that is needed for
  839. # public use; it is the "super"-constructor and is able to select an
  840. # adequate "sub"-constructor for a particular compression using the mapping
  841. # from OPEN_METH.
  842. #
  843. # This concept allows one to subclass TarFile without losing the comfort of
  844. # the super-constructor. A sub-constructor is registered and made available
  845. # by adding it to the mapping in OPEN_METH.
  846.  
  847. @classmethod
  848. def open(cls, name=None, mode="r", fileobj=None, bufsize=RECORDSIZE, **kwargs):
  849. """Open a tar archive for reading, writing or appending. Return
  850. an appropriate TarFile class.
  851.  
  852. mode:
  853. 'r' or 'r:*' open for reading with transparent compression
  854. 'r:' open for reading exclusively uncompressed
  855. 'r:gz' open for reading with gzip compression
  856. 'r:bz2' open for reading with bzip2 compression
  857. 'a' or 'a:' open for appending, creating the file if necessary
  858. 'w' or 'w:' open for writing without compression
  859. 'w:gz' open for writing with gzip compression
  860. 'w:bz2' open for writing with bzip2 compression
  861.  
  862. 'r|*' open a stream of tar blocks with transparent compression
  863. 'r|' open an uncompressed stream of tar blocks for reading
  864. 'r|gz' open a gzip compressed stream of tar blocks
  865. 'r|bz2' open a bzip2 compressed stream of tar blocks
  866. 'w|' open an uncompressed stream for writing
  867. 'w|gz' open a gzip compressed stream for writing
  868. 'w|bz2' open a bzip2 compressed stream for writing
  869. """
  870.  
  871. if not name and not fileobj:
  872. raise ValueError("nothing to open")
  873.  
  874. if mode in ("r", "r:*"):
  875. # Find out which *open() is appropriate for opening the file.
  876. for comptype in cls.OPEN_METH:
  877. func = getattr(cls, cls.OPEN_METH[comptype])
  878. if fileobj is not None:
  879. saved_pos = fileobj.tell()
  880. try:
  881. return func(name, "r", fileobj, **kwargs)
  882. except (ReadError, CompressionError), e:
  883. if fileobj is not None:
  884. fileobj.seek(saved_pos)
  885. continue
  886. raise ReadError("file could not be opened successfully")
  887.  
  888. elif ":" in mode:
  889. filemode, comptype = mode.split(":", 1)
  890. filemode = filemode or "r"
  891. comptype = comptype or "tar"
  892.  
  893. # Select the *open() function according to
  894. # given compression.
  895. if comptype in cls.OPEN_METH:
  896. func = getattr(cls, cls.OPEN_METH[comptype])
  897. else:
  898. raise CompressionError("unknown compression type %r" % comptype)
  899. return func(name, filemode, fileobj, **kwargs)
  900.  
  901. elif "|" in mode:
  902. filemode, comptype = mode.split("|", 1)
  903. filemode = filemode or "r"
  904. comptype = comptype or "tar"
  905.  
  906. if filemode not in ("r", "w"):
  907. raise ValueError("mode must be 'r' or 'w'")
  908.  
  909. stream = _Stream(name, filemode, comptype, fileobj, bufsize)
  910. try:
  911. t = cls(name, filemode, stream, **kwargs)
  912. except:
  913. stream.close()
  914. raise
  915. t._extfileobj = False
  916. return t
  917.  
  918. elif mode in ("a", "w"):
  919. return cls.taropen(name, mode, fileobj, **kwargs)
  920.  
  921. raise ValueError("undiscernible mode")
  922.  
  923. @classmethod
  924. def taropen(cls, name, mode="r", fileobj=None, **kwargs):
  925. """Open uncompressed tar archive name for reading or writing.
  926. """
  927. if mode not in ("r", "a", "w"):
  928. raise ValueError("mode must be 'r', 'a' or 'w'")
  929. return cls(name, mode, fileobj, **kwargs)
  930.  
  931. @classmethod
  932. def gzopen(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
  933. """Open gzip compressed tar archive name for reading or writing.
  934. Appending is not allowed.
  935. """
  936. if mode not in ("r", "w"):
  937. raise ValueError("mode must be 'r' or 'w'")
  938.  
  939. try:
  940. import gzip
  941. gzip.GzipFile
  942. except (ImportError, AttributeError):
  943. raise CompressionError("gzip module is not available")
  944.  
  945. try:
  946. fileobj = gzip.GzipFile(name, mode, compresslevel, fileobj)
  947. except OSError:
  948. if fileobj is not None and mode == 'r':
  949. raise ReadError("not a gzip file")
  950. raise
  951.  
  952. try:
  953. t = cls.taropen(name, mode, fileobj, **kwargs)
  954. except IOError:
  955. fileobj.close()
  956. if mode == 'r':
  957. raise ReadError("not a gzip file")
  958. raise
  959. except:
  960. fileobj.close()
  961. raise
  962. t._extfileobj = False
  963. return t
  964.  
  965. @classmethod
  966. def bz2open(cls, name, mode="r", fileobj=None, compresslevel=9, **kwargs):
  967. """Open bzip2 compressed tar archive name for reading or writing.
  968. Appending is not allowed.
  969. """
  970. if mode not in ("r", "w"):
  971. raise ValueError("mode must be 'r' or 'w'.")
  972.  
  973. try:
  974. import bz2
  975. except ImportError:
  976. raise CompressionError("bz2 module is not available")
  977.  
  978. if fileobj is not None:
  979. fileobj = _BZ2Proxy(fileobj, mode)
  980. else:
  981. fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel)
  982.  
  983. try:
  984. t = cls.taropen(name, mode, fileobj, **kwargs)
  985. except (IOError, EOFError):
  986. fileobj.close()
  987. if mode == 'r':
  988. raise ReadError("not a bzip2 file")
  989. raise
  990. except:
  991. fileobj.close()
  992. raise
  993. t._extfileobj = False
  994. return t
  995.  
  996. # All *open() methods are registered here.
  997. OPEN_METH = {
  998. "tar": "taropen", # uncompressed tar
  999. "gz": "gzopen", # gzip compressed tar
  1000. "bz2": "bz2open" # bzip2 compressed tar
  1001. }
  1002.  
  1003. #--------------------------------------------------------------------------
  1004. # The public methods which TarFile provides:
  1005.  
  1006. def close(self):
  1007. """Close the TarFile. In write-mode, two finishing zero blocks are
  1008. appended to the archive.
  1009. """
  1010. if self.closed:
  1011. return
  1012.  
  1013. if self.mode in "aw":
  1014. self.fileobj.write(NUL * (BLOCKSIZE * 2))
  1015. self.offset += (BLOCKSIZE * 2)
  1016. # fill up the end with zero-blocks
  1017. # (like option -b20 for tar does)
  1018. blocks, remainder = divmod(self.offset, RECORDSIZE)
  1019. if remainder > 0:
  1020. self.fileobj.write(NUL * (RECORDSIZE - remainder))
  1021.  
  1022. if not self._extfileobj:
  1023. self.fileobj.close()
  1024. self.closed = True
  1025.  
  1026. def getmember(self, name):
  1027. """Return a TarInfo object for member `name'. If `name' can not be
  1028. found in the archive, KeyError is raised. If a member occurs more
  1029. than once in the archive, its last occurrence is assumed to be the
  1030. most up-to-date version.
  1031. """
  1032. tarinfo = self._getmember(name)
  1033. if tarinfo is None:
  1034. raise KeyError("filename %r not found" % name)
  1035. return tarinfo
  1036.  
  1037. def getmembers(self):
  1038. """Return the members of the archive as a list of TarInfo objects. The
  1039. list has the same order as the members in the archive.
  1040. """
  1041. self._check()
  1042. if not self._loaded: # if we want to obtain a list of
  1043. self._load() # all members, we first have to
  1044. # scan the whole archive.
  1045. return self.members
  1046.  
  1047. def getnames(self):
  1048. """Return the members of the archive as a list of their names. It has
  1049. the same order as the list returned by getmembers().
  1050. """
  1051. return [tarinfo.name for tarinfo in self.getmembers()]
  1052.  
  1053. def gettarinfo(self, name=None, arcname=None, fileobj=None):
  1054. """Create a TarInfo object for either the file `name' or the file
  1055. object `fileobj' (using os.fstat on its file descriptor). You can
  1056. modify some of the TarInfo's attributes before you add it using
  1057. addfile(). If given, `arcname' specifies an alternative name for the
  1058. file in the archive.
  1059. """
  1060. self._check("aw")
  1061.  
  1062. # When fileobj is given, replace name by
  1063. # fileobj's real name.
  1064. if fileobj is not None:
  1065. name = fileobj.name
  1066.  
  1067. # Building the name of the member in the archive.
  1068. # Backward slashes are converted to forward slashes,
  1069. # Absolute paths are turned to relative paths.
  1070. if arcname is None:
  1071. arcname = name
  1072. drv, arcname = os.path.splitdrive(arcname)
  1073. arcname = arcname.replace(os.sep, "/")
  1074. arcname = arcname.lstrip("/")
  1075.  
  1076. # Now, fill the TarInfo object with
  1077. # information specific for the file.
  1078. tarinfo = self.tarinfo()
  1079. tarinfo.tarfile = self
  1080.  
  1081. # Use os.stat or os.lstat, depending on platform
  1082. # and if symlinks shall be resolved.
  1083. if fileobj is None:
  1084. if hasattr(os, "lstat") and not self.dereference:
  1085. statres = os.lstat(name)
  1086. else:
  1087. statres = os.stat(name)
  1088. else:
  1089. statres = os.fstat(fileobj.fileno())
  1090. linkname = ""
  1091.  
  1092. stmd = statres.st_mode
  1093. if stat.S_ISREG(stmd):
  1094. inode = (statres.st_ino, statres.st_dev)
  1095. if not self.dereference and statres.st_nlink > 1 and \
  1096. inode in self.inodes and arcname != self.inodes[inode]:
  1097. # Is it a hardlink to an already
  1098. # archived file?
  1099. type = LNKTYPE
  1100. linkname = self.inodes[inode]
  1101. else:
  1102. # The inode is added only if its valid.
  1103. # For win32 it is always 0.
  1104. type = REGTYPE
  1105. if inode[0]:
  1106. self.inodes[inode] = arcname
  1107. elif stat.S_ISDIR(stmd):
  1108. type = DIRTYPE
  1109. elif stat.S_ISFIFO(stmd):
  1110. type = FIFOTYPE
  1111. elif stat.S_ISLNK(stmd):
  1112. type = SYMTYPE
  1113. linkname = os.readlink(name)
  1114. elif stat.S_ISCHR(stmd):
  1115. type = CHRTYPE
  1116. elif stat.S_ISBLK(stmd):
  1117. type = BLKTYPE
  1118. else:
  1119. return None
  1120.  
  1121. # Fill the TarInfo object with all
  1122. # information we can get.
  1123. tarinfo.name = arcname
  1124. tarinfo.mode = stmd
  1125. tarinfo.uid = statres.st_uid
  1126. tarinfo.gid = statres.st_gid
  1127. if type == REGTYPE:
  1128. tarinfo.size = statres.st_size
  1129. else:
  1130. tarinfo.size = 0L
  1131. tarinfo.mtime = statres.st_mtime
  1132. tarinfo.type = type
  1133. tarinfo.linkname = linkname
  1134. if pwd:
  1135. try:
  1136. tarinfo.uname = pwd.getpwuid(tarinfo.uid)[0]
  1137. except KeyError:
  1138. pass
  1139. if grp:
  1140. try:
  1141. tarinfo.gname = grp.getgrgid(tarinfo.gid)[0]
  1142. except KeyError:
  1143. pass
  1144.  
  1145. if type in (CHRTYPE, BLKTYPE):
  1146. if hasattr(os, "major") and hasattr(os, "minor"):
  1147. tarinfo.devmajor = os.major(statres.st_rdev)
  1148. tarinfo.devminor = os.minor(statres.st_rdev)
  1149. return tarinfo
  1150.  
  1151. def list(self, verbose=True):
  1152. """Print a table of contents to sys.stdout. If `verbose' is False, only
  1153. the names of the members are printed. If it is True, an `ls -l'-like
  1154. output is produced.
  1155. """
  1156. self._check()
  1157.  
  1158. for tarinfo in self:
  1159. if verbose:
  1160. print filemode(tarinfo.mode),
  1161. print "%s/%s" % (tarinfo.uname or tarinfo.uid,
  1162. tarinfo.gname or tarinfo.gid),
  1163. if tarinfo.ischr() or tarinfo.isblk():
  1164. print "%10s" % ("%d,%d" \
  1165. % (tarinfo.devmajor, tarinfo.devminor)),
  1166. else:
  1167. print "%10d" % tarinfo.size,
  1168. print "%d-%02d-%02d %02d:%02d:%02d" \
  1169. % time.localtime(tarinfo.mtime)[:6],
  1170.  
  1171. print tarinfo.name + ("/" if tarinfo.isdir() else ""),
  1172.  
  1173. if verbose:
  1174. if tarinfo.issym():
  1175. print "->", tarinfo.linkname,
  1176. if tarinfo.islnk():
  1177. print "link to", tarinfo.linkname,
  1178. print
  1179.  
  1180. def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
  1181. """Add the file `name' to the archive. `name' may be any type of file
  1182. (directory, fifo, symbolic link, etc.). If given, `arcname'
  1183. specifies an alternative name for the file in the archive.
  1184. Directories are added recursively by default. This can be avoided by
  1185. setting `recursive' to False. `exclude' is a function that should
  1186. return True for each filename to be excluded. `filter' is a function
  1187. that expects a TarInfo object argument and returns the changed
  1188. TarInfo object, if it returns None the TarInfo object will be
  1189. excluded from the archive.
  1190. """
  1191. self._check("aw")
  1192.  
  1193. if arcname is None:
  1194. arcname = name
  1195.  
  1196. # Exclude pathnames.
  1197. if exclude is not None:
  1198. import warnings
  1199. warnings.warn("use the filter argument instead",
  1200. DeprecationWarning, 2)
  1201. if exclude(name):
  1202. self._dbg(2, "tarfile: Excluded %r" % name)
  1203. return
  1204.  
  1205. # Skip if somebody tries to archive the archive...
  1206. if self.name is not None and os.path.abspath(name) == self.name:
  1207. self._dbg(2, "tarfile: Skipped %r" % name)
  1208. return
  1209.  
  1210. self._dbg(1, name)
  1211.  
  1212. # Create a TarInfo object from the file.
  1213. tarinfo = self.gettarinfo(name, arcname)
  1214.  
  1215. if tarinfo is None:
  1216. self._dbg(1, "tarfile: Unsupported type %r" % name)
  1217. return
  1218.  
  1219. # Change or exclude the TarInfo object.
  1220. if filter is not None:
  1221. tarinfo = filter(tarinfo)
  1222. if tarinfo is None:
  1223. self._dbg(2, "tarfile: Excluded %r" % name)
  1224. return
  1225.  
  1226. # Append the tar header and data to the archive.
  1227. if tarinfo.isreg():
  1228. with bltn_open(name, "rb") as f:
  1229. self.addfile(tarinfo, f)
  1230.  
  1231. elif tarinfo.isdir():
  1232. self.addfile(tarinfo)
  1233. if recursive:
  1234. for f in os.listdir(name):
  1235. self.add(os.path.join(name, f), os.path.join(arcname, f),
  1236. recursive, exclude, filter)
  1237.  
  1238. else:
  1239. self.addfile(tarinfo)
  1240.  
  1241. def addfile(self, tarinfo, fileobj=None):
  1242. """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is
  1243. given, tarinfo.size bytes are read from it and added to the archive.
  1244. You can create TarInfo objects using gettarinfo().
  1245. On Windows platforms, `fileobj' should always be opened with mode
  1246. 'rb' to avoid irritation about the file size.
  1247. """
  1248. self._check("aw")
  1249.  
  1250. tarinfo = copy.copy(tarinfo)
  1251.  
  1252. buf = tarinfo.tobuf(self.format, self.encoding, self.errors)
  1253. self.fileobj.write(buf)
  1254. self.offset += len(buf)
  1255.  
  1256. # If there's data to follow, append it.
  1257. if fileobj is not None:
  1258. copyfileobj(fileobj, self.fileobj, tarinfo.size)
  1259. blocks, remainder = divmod(tarinfo.size, BLOCKSIZE)
  1260. if remainder > 0:
  1261. self.fileobj.write(NUL * (BLOCKSIZE - remainder))
  1262. blocks += 1
  1263. self.offset += blocks * BLOCKSIZE
  1264.  
  1265. self.members.append(tarinfo)
  1266.  
  1267. def extractall(self, path=".", members=None):
  1268. """Extract all members from the archive to the current working
  1269. directory and set owner, modification time and permissions on
  1270. directories afterwards. `path' specifies a different directory
  1271. to extract to. `members' is optional and must be a subset of the
  1272. list returned by getmembers().
  1273. """
  1274. directories = []
  1275.  
  1276. if members is None:
  1277. members = self
  1278.  
  1279. for tarinfo in members:
  1280. if tarinfo.isdir():
  1281. # Extract directories with a safe mode.
  1282. directories.append(tarinfo)
  1283. tarinfo = copy.copy(tarinfo)
  1284. tarinfo.mode = 0700
  1285. self.extract(tarinfo, path)
  1286.  
  1287. # Reverse sort directories.
  1288. directories.sort(key=operator.attrgetter('name'))
  1289. directories.reverse()
  1290.  
  1291. # Set correct owner, mtime and filemode on directories.
  1292. for tarinfo in directories:
  1293. dirpath = os.path.join(path, tarinfo.name)
  1294. try:
  1295. self.chown(tarinfo, dirpath)
  1296. self.utime(tarinfo, dirpath)
  1297. self.chmod(tarinfo, dirpath)
  1298. except ExtractError, e:
  1299. if self.errorlevel > 1:
  1300. raise
  1301. else:
  1302. self._dbg(1, "tarfile: %s" % e)
  1303.  
  1304. def extract(self, member, path=""):
  1305. """Extract a member from the archive to the current working directory,
  1306. using its full name. Its file information is extracted as accurately
  1307. as possible. `member' may be a filename or a TarInfo object. You can
  1308. specify a different directory using `path'.
  1309. """
  1310. self._check("r")
  1311.  
  1312. if isinstance(member, basestring):
  1313. tarinfo = self.getmember(member)
  1314. else:
  1315. tarinfo = member
  1316.  
  1317. # Prepare the link target for makelink().
  1318. if tarinfo.islnk():
  1319. tarinfo._link_target = os.path.join(path, tarinfo.linkname)
  1320.  
  1321. try:
  1322. self._extract_member(tarinfo, os.path.join(path, tarinfo.name))
  1323. except EnvironmentError, e:
  1324. if self.errorlevel > 0:
  1325. raise
  1326. else:
  1327. if e.filename is None:
  1328. self._dbg(1, "tarfile: %s" % e.strerror)
  1329. else:
  1330. self._dbg(1, "tarfile: %s %r" % (e.strerror, e.filename))
  1331. except ExtractError, e:
  1332. if self.errorlevel > 1:
  1333. raise
  1334. else:
  1335. self._dbg(1, "tarfile: %s" % e)
  1336.  
  1337. def extractfile(self, member):
  1338. """Extract a member from the archive as a file object. `member' may be
  1339. a filename or a TarInfo object. If `member' is a regular file, a
  1340. file-like object is returned. If `member' is a link, a file-like
  1341. object is constructed from the link's target. If `member' is none of
  1342. the above, None is returned.
  1343. The file-like object is read-only and provides the following
  1344. methods: read(), readline(), readlines(), seek() and tell()
  1345. """
  1346. self._check("r")
  1347.  
  1348. if isinstance(member, basestring):
  1349. tarinfo = self.getmember(member)
  1350. else:
  1351. tarinfo = member
  1352.  
  1353. if tarinfo.isreg():
  1354. return self.fileobject(self, tarinfo)
  1355.  
  1356. elif tarinfo.type not in SUPPORTED_TYPES:
  1357. # If a member's type is unknown, it is treated as a
  1358. # regular file.
  1359. return self.fileobject(self, tarinfo)
  1360.  
  1361. elif tarinfo.islnk() or tarinfo.issym():
  1362. if isinstance(self.fileobj, _Stream):
  1363. # A small but ugly workaround for the case that someone tries
  1364. # to extract a (sym)link as a file-object from a non-seekable
  1365. # stream of tar blocks.
  1366. raise StreamError("cannot extract (sym)link as file object")
  1367. else:
  1368. # A (sym)link's file object is its target's file object.
  1369. return self.extractfile(self._find_link_target(tarinfo))
  1370. else:
  1371. # If there's no data associated with the member (directory, chrdev,
  1372. # blkdev, etc.), return None instead of a file object.
  1373. return None
  1374.  
  1375. def _extract_member(self, tarinfo, targetpath):
  1376. """Extract the TarInfo object tarinfo to a physical
  1377. file called targetpath.
  1378. """
  1379. # Fetch the TarInfo object for the given name
  1380. # and build the destination pathname, replacing
  1381. # forward slashes to platform specific separators.
  1382. targetpath = targetpath.rstrip("/")
  1383. targetpath = targetpath.replace("/", os.sep)
  1384.  
  1385. # Create all upper directories.
  1386. upperdirs = os.path.dirname(targetpath)
  1387. if upperdirs and not os.path.exists(upperdirs):
  1388. # Create directories that are not part of the archive with
  1389. # default permissions.
  1390. os.makedirs(upperdirs)
  1391.  
  1392. if tarinfo.islnk() or tarinfo.issym():
  1393. self._dbg(1, "%s -> %s" % (tarinfo.name, tarinfo.linkname))
  1394. else:
  1395. self._dbg(1, tarinfo.name)
  1396.  
  1397. if tarinfo.isreg():
  1398. self.makefile(tarinfo, targetpath)
  1399. elif tarinfo.isdir():
  1400. self.makedir(tarinfo, targetpath)
  1401. elif tarinfo.isfifo():
  1402. self.makefifo(tarinfo, targetpath)
  1403. elif tarinfo.ischr() or tarinfo.isblk():
  1404. self.makedev(tarinfo, targetpath)
  1405. elif tarinfo.islnk() or tarinfo.issym():
  1406. self.makelink(tarinfo, targetpath)
  1407. elif tarinfo.type not in SUPPORTED_TYPES:
  1408. self.makeunknown(tarinfo, targetpath)
  1409. else:
  1410. self.makefile(tarinfo, targetpath)
  1411.  
  1412. self.chown(tarinfo, targetpath)
  1413. if not tarinfo.issym():
  1414. self.chmod(tarinfo, targetpath)
  1415. self.utime(tarinfo, targetpath)
  1416.  
  1417. #--------------------------------------------------------------------------
  1418. # Below are the different file methods. They are called via
  1419. # _extract_member() when extract() is called. They can be replaced in a
  1420. # subclass to implement other functionality.
  1421.  
  1422. def makedir(self, tarinfo, targetpath):
  1423. """Make a directory called targetpath.
  1424. """
  1425. try:
  1426. # Use a safe mode for the directory, the real mode is set
  1427. # later in _extract_member().
  1428. os.mkdir(targetpath, 0700)
  1429. except EnvironmentError, e:
  1430. if e.errno != errno.EEXIST:
  1431. raise
  1432.  
  1433. def makefile(self, tarinfo, targetpath):
  1434. """Make a file called targetpath.
  1435. """
  1436. source = self.extractfile(tarinfo)
  1437. try:
  1438. with bltn_open(targetpath, "wb") as target:
  1439. copyfileobj(source, target)
  1440. finally:
  1441. source.close()
  1442.  
  1443. def makeunknown(self, tarinfo, targetpath):
  1444. """Make a file from a TarInfo object with an unknown type
  1445. at targetpath.
  1446. """
  1447. self.makefile(tarinfo, targetpath)
  1448. self._dbg(1, "tarfile: Unknown file type %r, " \
  1449. "extracted as regular file." % tarinfo.type)
  1450.  
  1451. def makefifo(self, tarinfo, targetpath):
  1452. """Make a fifo called targetpath.
  1453. """
  1454. if hasattr(os, "mkfifo"):
  1455. os.mkfifo(targetpath)
  1456. else:
  1457. raise ExtractError("fifo not supported by system")
  1458.  
  1459. def makedev(self, tarinfo, targetpath):
  1460. """Make a character or block device called targetpath.
  1461. """
  1462. if not hasattr(os, "mknod") or not hasattr(os, "makedev"):
  1463. raise ExtractError("special devices not supported by system")
  1464.  
  1465. mode = tarinfo.mode
  1466. if tarinfo.isblk():
  1467. mode |= stat.S_IFBLK
  1468. else:
  1469. mode |= stat.S_IFCHR
  1470.  
  1471. os.mknod(targetpath, mode,
  1472. os.makedev(tarinfo.devmajor, tarinfo.devminor))
  1473.  
  1474. def makelink(self, tarinfo, targetpath):
  1475. """Make a (symbolic) link called targetpath. If it cannot be created
  1476. (platform limitation), we try to make a copy of the referenced file
  1477. instead of a link.
  1478. """
  1479. if hasattr(os, "symlink") and hasattr(os, "link"):
  1480. # For systems that support symbolic and hard links.
  1481. if tarinfo.issym():
  1482. if os.path.lexists(targetpath):
  1483. os.unlink(targetpath)
  1484. os.symlink(tarinfo.linkname, targetpath)
  1485. else:
  1486. # See extract().
  1487. if os.path.exists(tarinfo._link_target):
  1488. if os.path.lexists(targetpath):
  1489. os.unlink(targetpath)
  1490. os.link(tarinfo._link_target, targetpath)
  1491. else:
  1492. self._extract_member(self._find_link_target(tarinfo), targetpath)
  1493. else:
  1494. try:
  1495. self._extract_member(self._find_link_target(tarinfo), targetpath)
  1496. except KeyError:
  1497. raise ExtractError("unable to resolve link inside archive")
  1498.  
  1499. def chown(self, tarinfo, targetpath):
  1500. """Set owner of targetpath according to tarinfo.
  1501. """
  1502. if pwd and hasattr(os, "geteuid") and os.geteuid() == 0:
  1503. # We have to be root to do so.
  1504. try:
  1505. g = grp.getgrnam(tarinfo.gname)[2]
  1506. except KeyError:
  1507. g = tarinfo.gid
  1508. try:
  1509. u = pwd.getpwnam(tarinfo.uname)[2]
  1510. except KeyError:
  1511. u = tarinfo.uid
  1512. try:
  1513. if tarinfo.issym() and hasattr(os, "lchown"):
  1514. os.lchown(targetpath, u, g)
  1515. else:
  1516. if sys.platform != "os2emx":
  1517. os.chown(targetpath, u, g)
  1518. except EnvironmentError, e:
  1519. raise ExtractError("could not change owner")
  1520.  
  1521. def chmod(self, tarinfo, targetpath):
  1522. """Set file permissions of targetpath according to tarinfo.
  1523. """
  1524. if hasattr(os, 'chmod'):
  1525. try:
  1526. os.chmod(targetpath, tarinfo.mode)
  1527. except EnvironmentError, e:
  1528. raise ExtractError("could not change mode")
  1529.  
  1530. def utime(self, tarinfo, targetpath):
  1531. """Set modification time of targetpath according to tarinfo.
  1532. """
  1533. if not hasattr(os, 'utime'):
  1534. return
  1535. try:
  1536. os.utime(targetpath, (tarinfo.mtime, tarinfo.mtime))
  1537. except EnvironmentError, e:
  1538. raise ExtractError("could not change modification time")
  1539.  
  1540. #--------------------------------------------------------------------------
  1541. def next(self):
  1542. """Return the next member of the archive as a TarInfo object, when
  1543. TarFile is opened for reading. Return None if there is no more
  1544. available.
  1545. """
  1546. self._check("ra")
  1547. if self.firstmember is not None:
  1548. m = self.firstmember
  1549. self.firstmember = None
  1550. return m
  1551.  
  1552. # Read the next block.
  1553. self.fileobj.seek(self.offset)
  1554. tarinfo = None
  1555. while True:
  1556. try:
  1557. tarinfo = self.tarinfo.fromtarfile(self)
  1558. except EOFHeaderError, e:
  1559. if self.ignore_zeros:
  1560. self._dbg(2, "0x%X: %s" % (self.offset, e))
  1561. self.offset += BLOCKSIZE
  1562. continue
  1563. except InvalidHeaderError, e:
  1564. if self.ignore_zeros:
  1565. self._dbg(2, "0x%X: %s" % (self.offset, e))
  1566. self.offset += BLOCKSIZE
  1567. continue
  1568. elif self.offset == 0:
  1569. raise ReadError(str(e))
  1570. except EmptyHeaderError:
  1571. if self.offset == 0:
  1572. raise ReadError("empty file")
  1573. except TruncatedHeaderError, e:
  1574. if self.offset == 0:
  1575. raise ReadError(str(e))
  1576. except SubsequentHeaderError, e:
  1577. raise ReadError(str(e))
  1578. break
  1579.  
  1580. if tarinfo is not None:
  1581. self.members.append(tarinfo)
  1582. else:
  1583. self._loaded = True
  1584.  
  1585. return tarinfo
  1586.  
  1587. #--------------------------------------------------------------------------
  1588. # Little helper methods:
  1589.  
  1590. def _getmember(self, name, tarinfo=None, normalize=False):
  1591. """Find an archive member by name from bottom to top.
  1592. If tarinfo is given, it is used as the starting point.
  1593. """
  1594. # Ensure that all members have been loaded.
  1595. members = self.getmembers()
  1596.  
  1597. # Limit the member search list up to tarinfo.
  1598. if tarinfo is not None:
  1599. members = members[:members.index(tarinfo)]
  1600.  
  1601. if normalize:
  1602. name = os.path.normpath(name)
  1603.  
  1604. for member in reversed(members):
  1605. if normalize:
  1606. member_name = os.path.normpath(member.name)
  1607. else:
  1608. member_name = member.name
  1609.  
  1610. if name == member_name:
  1611. return member
  1612.  
  1613. def _load(self):
  1614. """Read through the entire archive file and look for readable
  1615. members.
  1616. """
  1617. while True:
  1618. tarinfo = self.next()
  1619. if tarinfo is None:
  1620. break
  1621. self._loaded = True
  1622.  
  1623. def _check(self, mode=None):
  1624. """Check if TarFile is still open, and if the operation's mode
  1625. corresponds to TarFile's mode.
  1626. """
  1627. if self.closed:
  1628. raise IOError("%s is closed" % self.__class__.__name__)
  1629. if mode is not None and self.mode not in mode:
  1630. raise IOError("bad operation for mode %r" % self.mode)
  1631.  
  1632. def _find_link_target(self, tarinfo):
  1633. """Find the target member of a symlink or hardlink member in the
  1634. archive.
  1635. """
  1636. if tarinfo.issym():
  1637. # Always search the entire archive.
  1638. linkname = "/".join(filter(None, (os.path.dirname(tarinfo.name), tarinfo.linkname)))
  1639. limit = None
  1640. else:
  1641. # Search the archive before the link, because a hard link is
  1642. # just a reference to an already archived file.
  1643. linkname = tarinfo.linkname
  1644. limit = tarinfo
  1645.  
  1646. member = self._getmember(linkname, tarinfo=limit, normalize=True)
  1647. if member is None:
  1648. raise KeyError("linkname %r not found" % linkname)
  1649. return member
  1650.  
  1651. def __iter__(self):
  1652. """Provide an iterator object.
  1653. """
  1654. if self._loaded:
  1655. return iter(self.members)
  1656. else:
  1657. return TarIter(self)
  1658.  
  1659. def _dbg(self, level, msg):
  1660. """Write debugging output to sys.stderr.
  1661. """
  1662. if level <= self.debug:
  1663. print >> sys.stderr, msg
  1664.  
  1665. def __enter__(self):
  1666. self._check()
  1667. return self
  1668.  
  1669. def __exit__(self, type, value, traceback):
  1670. if type is None:
  1671. self.close()
  1672. else:
  1673. # An exception occurred. We must not call close() because
  1674. # it would try to write end-of-archive blocks and padding.
  1675. if not self._extfileobj:
  1676. self.fileobj.close()
  1677. self.closed = True
  1678. # class TarFile

七、ConfigParser

用于对特定的配置进行操作,当前模块的名称在 python 3.x 版本中变更为 configparser。

1
2
3
4
5
6
7
8
9
# 注释1
; 注释2
 
[section1]
k1 = v1
k2:v2
 
[section2]
k1 = v1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import ConfigParser
 
config = ConfigParser.ConfigParser()
config.read('i.cfg')
 
# ########## 读 ##########
#secs = config.sections()
#print secs
#options = config.options('group2')
#print options
 
#item_list = config.items('group2')
#print item_list
 
#val = config.get('group1','key')
#val = config.getint('group1','key')
 
# ########## 改写 ##########
#sec = config.remove_section('group1')
#config.write(open('i.cfg', "w"))
 
#sec = config.has_section('wupeiqi')
#sec = config.add_section('wupeiqi')
#config.write(open('i.cfg', "w"))
 
 
#config.set('group2','k1',11111)
#config.write(open('i.cfg', "w"))
 
#config.remove_option('group2','age')
#config.write(open('i.cfg', "w"))

八、logging

用于便捷记录日志且线程安全的模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import logging
 
 
logging.basicConfig(filename='log.log',
                    format='%(asctime)s - %(name)s - %(levelname)s -%(module)s:  %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S %p',
                    level=10)
 
logging.debug('debug')
logging.info('info')
logging.warning('warning')
logging.error('error')
logging.critical('critical')
logging.log(10,'log')

对于等级:

1
2
3
4
5
6
7
8
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0

只有大于当前日志等级的操作才会被记录。

对于格式,有如下属性可是配置:

九、time

时间相关的操作,时间有三种表示方式:

  • 时间戳               1970年1月1日之后的秒,即:time.time()
  • 格式化的字符串    2014-11-11 11:11,    即:time.strftime('%Y-%m-%d')
  • 结构化时间          元组包含了:年、日、星期等... time.struct_time    即:time.localtime()
  1. #_*_coding:utf-8_*_
  2. __author__ = 'Alex Li'
  3.  
  4. import time
  5.  
  6. # print(time.clock()) #返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定,mac上测不出来
  7. # print(time.altzone) #返回与utc时间的时间差,以秒计算\
  8. # print(time.asctime()) #返回时间格式"Fri Aug 19 11:14:16 2016",
  9. # print(time.localtime()) #返回本地时间 的struct time对象格式
  10. # print(time.gmtime(time.time()-800000)) #返回utc时间的struc时间对象格式
  11.  
  12. # print(time.asctime(time.localtime())) #返回时间格式"Fri Aug 19 11:14:16 2016",
  13. #print(time.ctime()) #返回Fri Aug 19 12:38:29 2016 格式, 同上
  14.  
  15. # 日期字符串 转成 时间戳
  16. # string_2_struct = time.strptime("2016/05/22","%Y/%m/%d") #将 日期字符串 转成 struct时间对象格式
  17. # print(string_2_struct)
  18. # #
  19. # struct_2_stamp = time.mktime(string_2_struct) #将struct时间对象转成时间戳
  20. # print(struct_2_stamp)
  21.  
  22. #将时间戳转为字符串格式
  23. # print(time.gmtime(time.time()-86640)) #将utc时间戳转换成struct_time格式
  24. # print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将utc struct_time格式转成指定的字符串格式
  25.  
  26. #时间加减
  27. import datetime
  28.  
  29. # print(datetime.datetime.now()) #返回 2016-08-19 12:47:03.941925
  30. #print(datetime.date.fromtimestamp(time.time()) ) # 时间戳直接转成日期格式 2016-08-19
  31. # print(datetime.datetime.now() )
  32. # print(datetime.datetime.now() + datetime.timedelta(3)) #当前时间+3天
  33. # print(datetime.datetime.now() + datetime.timedelta(-3)) #当前时间-3天
  34. # print(datetime.datetime.now() + datetime.timedelta(hours=3)) #当前时间+3小时
  35. # print(datetime.datetime.now() + datetime.timedelta(minutes=30)) #当前时间+30分
  36.  
  37. #
  38. # c_time = datetime.datetime.now()
  39. # print(c_time.replace(minute=3,hour=2)) #时间替换

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
print time.time()
print time.mktime(time.localtime())
  
print time.gmtime()    #可加时间戳参数
print time.localtime() #可加时间戳参数
print time.strptime('2014-11-11''%Y-%m-%d')
  
print time.strftime('%Y-%m-%d'#默认当前时间
print time.strftime('%Y-%m-%d',time.localtime()) #默认当前时间
print time.asctime()
print time.asctime(time.localtime())
print time.ctime(time.time())
  
import datetime
'''
datetime.date:表示日期的类。常用的属性有year, month, day
datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond
datetime.datetime:表示日期时间
datetime.timedelta:表示时间间隔,即两个时间点之间的长度
timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
strftime("%Y-%m-%d")
'''
import datetime
print datetime.datetime.now()
print datetime.datetime.now() - datetime.timedelta(days=5)

十、re 

re模块用于对python的正则表达式的操作。

字符:

  . 匹配除换行符以外的任意字符
  \w 匹配字母或数字或下划线或汉字
  \s 匹配任意的空白符
  \d 匹配数字
  \b 匹配单词的开始或结束
  ^ 匹配字符串的开始
  $ 匹配字符串的结束

次数:

  * 重复零次或更多次
  + 重复一次或更多次
  ? 重复零次或一次
  {n} 重复n次
  {n,} 重复n次或更多次
  {n,m} 重复n到m次

  1. IP
  2. ^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$
  3. 手机号:
  4. ^1[3|4|5|8][0-9]\d{8}$

1、match(pattern, string, flags=0)

从起始位置开始根据模型去字符串中匹配指定内容,匹配单个

  • 正则表达式
  • 要匹配的字符串
  • 标志位,用于控制正则表达式的匹配方式
  1. import re
  2.  
  3. obj = re.match('\d+', '123uuasf')
  4. if obj:
  5. print obj.group()
  1. # flags
  2. I = IGNORECASE = sre_compile.SRE_FLAG_IGNORECASE # ignore case
  3. L = LOCALE = sre_compile.SRE_FLAG_LOCALE # assume current 8-bit locale
  4. U = UNICODE = sre_compile.SRE_FLAG_UNICODE # assume unicode locale
  5. M = MULTILINE = sre_compile.SRE_FLAG_MULTILINE # make anchors look for newline
  6. S = DOTALL = sre_compile.SRE_FLAG_DOTALL # make dot match newline
  7. X = VERBOSE = sre_compile.SRE_FLAG_VERBOSE # ignore whitespace and comments
  8.  
  9. flags

2、search(pattern, string, flags=0)

根据模型去字符串中匹配指定内容,匹配单个

  1. import re
  2.  
  3. obj = re.search('\d+', 'u123uu888asf')
  4. if obj:
  5. print obj.group()

3、group和groups

  1. a = "123abc456"
  2. print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group()
  3.  
  4. print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0)
  5. print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1)
  6. print re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2)
  7.  
  8. print re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups()

4、findall(pattern, string, flags=0)

上述两中方式均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用 findall。

  1. import re
  2.  
  3. obj = re.findall('\d+', 'fa123uu888asf')
  4. print obj

5、sub(pattern, repl, string, count=0, flags=0)

用于替换匹配的字符串

  1. content = "123abc456"
  2. new_content = re.sub('\d+', 'sb', content)
  3. # new_content = re.sub('\d+', 'sb', content, 1)
  4. print new_content

相比于str.replace功能更加强大

6、split(pattern, string, maxsplit=0, flags=0)

根据指定匹配进行分组

  1. content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
  2. new_content = re.split('\*', content)
  3. # new_content = re.split('\*', content, 1)
  4. print new_content
  1. content = "'1 - 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2) )'"
  2. new_content = re.split('[\+\-\*\/]+', content)
  3. # new_content = re.split('\*', content, 1)
  4. print new_content
  1. inpp = '1-2*((60-30 +(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))'
  2. inpp = re.sub('\s*','',inpp)
  3. new_content = re.split('\(([\+\-\*\/]?\d+[\+\-\*\/]?\d+){1}\)', inpp, 1)
  4. print new_content

相比于str.split更加强大

实例:计算器源码

十一、random

随机数

1
2
3
4
mport random
print random.random()
print random.randint(1,2)
print random.randrange(1,10)

随机验证码实例:

1
2
3
4
5
6
7
8
9
10
import random
checkcode = ''
for in range(4):
    current = random.randrange(0,4)
    if current != i:
        temp = chr(random.randint(65,90))
    else:
        temp = random.randint(0,9)
    checkcode += str(temp)
print checkcode

  

Python全栈开发:模块的更多相关文章

  1. Python全栈开发【模块】

    Python全栈开发[模块] 本节内容: 模块介绍 time random os sys json & picle shelve XML hashlib ConfigParser loggin ...

  2. python全栈开发中级班全程笔记(第二模块、第四章(三、re 正则表达式))

    python全栈开发笔记第二模块   第四章 :常用模块(第三部分) 一.正则表达式的作用与方法 正则表达式是什么呢?一个问题带来正则表达式的重要性和作用      有一个需求 : 从文件中读取所有联 ...

  3. python全栈开发中级班全程笔记(第二模块、第四章)(常用模块导入)

    python全栈开发笔记第二模块 第四章 :常用模块(第二部分)     一.os 模块的 详解 1.os.getcwd()    :得到当前工作目录,即当前python解释器所在目录路径 impor ...

  4. python全栈开发之正则表达式和python的re模块

    正则表达式和python的re模块 python全栈开发,正则表达式,re模块 一 正则表达式 正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的 ...

  5. python全栈开发中级班全程笔记(第二模块、第三章)(员工信息增删改查作业讲解)

    python全栈开发中级班全程笔记 第三章:员工信息增删改查作业代码 作业要求: 员工增删改查表用代码实现一个简单的员工信息增删改查表需求: 1.支持模糊查询,(1.find name ,age fo ...

  6. Python全栈开发【面向对象进阶】

    Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...

  7. Python全栈开发【面向对象】

    Python全栈开发[面向对象] 本节内容: 三大编程范式 面向对象设计与面向对象编程 类和对象 静态属性.类方法.静态方法 类组合 继承 多态 封装 三大编程范式 三大编程范式: 1.面向过程编程 ...

  8. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  9. Python全栈开发【基础一】

    Python全栈开发[第一篇] 本节内容: Python 的种类 Python 的环境 Python 入门(解释器.编码.变量.input输入.if流程控制与缩进.while循环) if流程控制与wh ...

  10. python全栈开发-Day2 布尔、流程控制、循环

    python全栈开发-Day2 布尔 流程控制 循环   一.布尔 1.概述 #布尔值,一个True一个False #计算机俗称电脑,即我们编写程序让计算机运行时,应该是让计算机无限接近人脑,或者说人 ...

随机推荐

  1. favicon.ico请求处理

    favicon.ico 图标用于收藏夹图标和浏览器标签上的显示,如果不设置,浏览器会请求网站根目录的这个图标,如果网站根目录也没有这图标会产生 404. 出于优化的考虑,要么就有这个图标,要么就禁止产 ...

  2. [JZOJ 5697] 农场

    题目大意:将 n 个数 ai分成若干连续的段,使得每段的和都相等,求最多可以分成多少段. 思路: 考虑ai的和为sum,那么每一段的和就是约数. 对于每一个d,考虑其是否合法. 1e6之内用桶统计不会 ...

  3. hdu多校第五场1006 (hdu6629) string matching Ex-KMP

    题意: 给你一个暴力匹配字符串公共前缀后缀的程序,为你对于某个字符串,暴力匹配的次数是多少. 题解: 使用扩展kmp构造extend数组,在扩展kmp中,设原串S和模式串T. extend[i]表示T ...

  4. POJ2226-Muddy Fields-二分图*

    目录 目录 思路: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 目录 题意:传送门  原题目描述在最下面.  一个nm的矩阵,有坑有草,可以用1x长度的木板盖住坑,但不能盖到草. ...

  5. [zz]winform 窗体关闭事件

    注册窗体关闭事件: 在Form1.Designer.cs 文件中添加: this.FormClosing += new System.Windows.Forms.FormClosingEventHan ...

  6. drools原生drl规则文件的使用

    在初识drools中对drl文件进行了简单的介绍.这里举个例子来具体说明下.主要是写了规则之后我们如何用java代码来run起来. drl文件内容如下: rule "ageUp12" ...

  7. 2019.2.23VScode的c++配置详细方法

    根据个人经验,最新的c++配置方法. 主要的步骤: 安装Vscode 在Vscode类安装c++插件 安装编译调试环境 修改Vscode配置文件. 安装Vscode的步骤省略 如何配置Vscode中文 ...

  8. Sublime Text自定制代码片段(Code Snippets)

    在编写代码的整个过程中,开发人员经常会一次又一次的改写或者重用相同的代码段,消除这种重复过程的方法之一是把我们经常用到的代码保存成代码片段(snippets),这使得我们可以方便的检索和使用它们. 为 ...

  9. 常用Oracle操作语句

    --常用的字段类型有:varchar2,char,nchar,date,long,number,float,BLOB,CLOB --添加表字段 ); --修改表字段 ); --删除表字段 alter ...

  10. [TJOI 2018]游园会

    题意:求NOI的合法串... 思路: 首先这个似乎和后缀自动机没关系(话说TJ不考后缀自动机??),其实就是一个\(DP\)套\(DP\),考虑如果不看兑奖串就是一个LCS,当出现时多记一维即可. # ...