记录Python常用的一些标准库,以及第三方库

argpaser

add_argument说明

  • name="square"
    • 没有-前缀的verbose` 是位置参数
  • -a短参数,--arg为长参数,是可选参数,短参数与长参数可以放一起
  • help="参数说明", 参数的说明
  • type=int,指定参数类型
  • action="store_true",如果指定了参数就将True赋值给args.square,否则为False
    • 默认需要提供value,--batch_size 2
    • store_true,可以不传值:--is_verbose
    • count,当参数出现n次就赋值为n,比如-vvv时,就有v=3
  • choices=[0, 1, 2],指定可以赋值的范围,与action="store_true"不兼容
  • default=0,指定默认值,否则是None

添加参数

位置参数

positional arguments

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", help="display a square of a given number", type=int)
args = parser.parse_args()
print(args.square**2)

##################用法################
python3 prog.py 4
16
可选参数

Optional arguments

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--verbosity", help="increase output verbosity")
args = parser.parse_args()
if args.verbosity:
    print("verbosity turned on")
##################用法################
python3 prog.py --verbosity 1
verbosity turned on

默认情况,可选参数后面必须跟一个value,--verbosity any

如果需要只是标志类型的参数,可以设置action="store_true"

二者选其一参数

使用add_mutually_exclusive_group可以实现两个参数只能设置其中一个的效果,比如想要设置打印日志为详细还是静默。

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument("-v", "--verbose", action="store_true")
group.add_argument("-q", "--quiet", action="store_true")
parser.add_argument("x", type=int, help="the base")
parser.add_argument("y", type=int, help="the exponent")
args = parser.parse_args()
answer = args.x**args.y

if args.quiet:
    print(answer)
elif args.verbose:
    print("{} to the power {} equals {}".format(args.x, args.y, answer))
else:
    print("{}^{} == {}".format(args.x, args.y, answer))

##################使用###############
$ python3 prog.py 4 2
4^2 == 16
$ python3 prog.py 4 2 -q
16
$ python3 prog.py 4 2 -v
4 to the power 2 equals 16
$ python3 prog.py 4 2 -vq
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose
$ python3 prog.py 4 2 -v --quiet
usage: prog.py [-h] [-v | -q] x y
prog.py: error: argument -q/--quiet: not allowed with argument -v/--verbose

最佳实践

import argparse


def paser_arg():
    """
    参数解析,以及默认参数设置
    :return:
    """
    parser = argparse.ArgumentParser(description="说明该模块的功能")
    add = parser.add_argument  #将该函数赋值给add,方便后面定义参数
    add("--verbose",help="是否显示详细日志内容")

    return parser.parse_args()

if "__main__" == __name__:
    options = paser_arg()
    if options.verbose:
        print("verbose print")
    else:
        print("no verbose print")

参考:官方argpaser

profile 性能分析

from profile import Profile
from pstats import Stats

def gcd(pair):
    """
    计算最大公约数
    """
    a, b = pair
    low = min(a, b)
    for i in range(low, 0, -1):
        if a % i == 0 and b % i == 0:
            return i

def main(n):
      """
      被测试的函数
      """
    i = 0
    while i<n:
        gcd((1963309, 2265973))
        i+=1

p = Profile()
p.runcall(main, 100)    # 函数,以及参数
# p.print_stats()            # 可以直接打印报告

# 使用stats可以更加自由的定义打印的报告内容
stats = Stats(p)
stats.strip_dirs()
stats.sort_stats('cumulative')
stats.print_stats()   
stats.print_callers()    # 打印每个函数的调用者
  203 function calls in 22.478 seconds

     Ordered by: standard name

     ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        100    0.001    0.000    0.001    0.000 :0(min)
          1    0.000    0.000    0.000    0.000 :0(setprofile)
          1    0.001    0.001   22.477   22.477 <ipython-input-13-1e3e5803ef86>:13(main)
        100   22.476    0.225   22.476    0.225 <ipython-input-13-1e3e5803ef86>:3(gcd)
          1    0.000    0.000   22.478   22.478 profile:0(<function main at 0x107c720d0>)
          0    0.000             0.000          profile:0(profiler)

   Ordered by: cumulative time

  Function                                   was called by...
  profile:0(<function main at 0x107dffbf8>)  <- profile:0(profiler)(1)    0.000
  <ipython-input-21-c6df0a564b27>:13(main)   <- profile:0(<function main at 0x107dffbf8>)(1)   22.548
  <ipython-input-21-c6df0a564b27>:3(gcd)     <- <ipython-input-21-c6df0a564b27>:13(main)(100)   22.547
  :0(min)                                    <- <ipython-input-21-c6df0a564b27>:3(gcd)(100)   22.546
  :0(setprofile)                             <- profile:0(<function main at 0x107dffbf8>)(1)   22.548
  profile:0(profiler)                        <- 

报告说明:

  • ncalls:该函数表调用的次数
  • cumtime:执行该函数的所花的时间,函数内调用其他函数的时间
  • tottime:执行该函数的所花的时间,s函数内调用其他函数的时间
  • percall:平均每次调用消耗的时间

pickle

The pickle module 实现了二进制协议,用于serializing 和 de-serializing Python object structure 并保存到磁盘中,并在需要的时候读取出来,任何对象(lambda除外)都可以执行序列化操作。

Pickle模块中最常用的函数为:

保存为文件

  1. dump(obj, file, [,protocol])

    功能:将obj对象序列化存入已经打开的file中。

    • obj: 想要序列化的obj对象。
    • file: file对象
    • protocol: 序列化使用的协议。如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
    with open('data.pickle', 'wb') as file:
        # 使用 highest protocol Pickle the 'data' dictionary 
        pickle.dump(data, file, pickle.HIGHEST_PROTOCOL)
    
  2. load(file)

    功能:将file中的对象反序列化读出。

    with open('data.pickle', 'rb') as file:
        # protocol版本会自动检测,不要指定
        data = pickle.load(file)
    

因为pickle是使用二进制保存文件,因此open的读写模式,要使用‘b’

保存为string

  1. dumps(obj [, protocol])

    功能:将obj对象序列化为string形式,而不是存入文件中。

    • obj:想要序列化的obj对象。
    • protocol:如果该项省略,则默认为0。如果为负值或HIGHEST_PROTOCOL,则使用最高的协议版本。
  2. loads(string)

    函数的功能:从string中读出序列化前的obj对象。

    • string:pickle序列化后的字符串对象
    import pickle
    # dumps
    li = [11,22,33]
    r = pickle.dumps(li)
    print(r)
    #(lp0
    # I11
    # aI22
    # aI33
    # a.
    
    # loads
    result = pickle.loads(r)
    print(result)
    # [11, 22, 33]
    

对函数、类、接口序列号

pickle 可以序列化函数,类,还有接口,但是结果数据仅仅将它们的名称编码成对应的代码对象。例如:

import math
import pickle.
pickle.dumps(math.cos)
# b'\x80\x03cmath\ncos\nq\x00.'

当数据反序列化回来的时候,会先假定所有的源数据时可用的。 模块、类和函数会自动按需导入进来。对于Python数据被不同机器上的解析器所共享的应用程序而言, 数据的保存可能会有问题,因为所有的机器都必须访问同一个源代码。

安全问题

千万不要对不信任的数据使用pickle.load()
pickle在加载时有一个副作用就是它会自动加载相应模块并构造实例对象。但是某个坏人如果知道pickle的工作原理,
他就可以创建一个恶意的数据导致Python执行随意指定的系统命令。因此,一定要保证pickle只在相互之间可以认证对方的解析器的内部使用

re

re

字符串查找
  • re.match:查找字符串中是否有”从头开始”匹配的非空子串,返回match对象
  • re.search:查找字符串中是否有匹配的非空子串,返回第一个匹配成功的match对象
  • re.finditer:查找字符串中所有满足正则表达式的子串,返回全部match对象的数组

    import re
    s="she said: \"I love you\",and he replied 'me,too'"
    ms=re.finditer(r"(?P<quote>['\"]).*?(?P=quote)",s)
    for m in ms:
      print(m.group(0))
    
    # "I love you"
    # 'me,too'
    
  • re.fullmatch:判断是否”整个字符串”满足正则表达式

  • re.findall:查找所有满足正则表达式的子串,返回全部子串的数组
字符串替换
  • re.sub

    函数调用:text = sub(pattern,repl,string,count)

    • pattern : 正则中的模式字符串
    • repl : 替换的字符串,sub() 函数除了接受替换字符串外,还能接受一个回调函数,(参数必须是 match 对象)
    • string:要被查找替换的原始字符串
    • count : 模式匹配后替换的最大次数,默认 0 表示替换 全部的匹配
  • re.subn

    函数调用:`newtext, n = re.subn()` ,`n`表示发生了多少次替换
    
字符串分割

re.split字符串分割,返回分割后的数组。注意括号的区别

import re
res=re.split("\|" , ' runoob|runoob|runoob.')
# [' runoob', 'runoob', 'runoob.']

res=re.split("(\|)" , ' runoob|runoob|runoob.') # 添加括号,会保留分割符
# [' runoob', '|', 'runoob', '|', 'runoob.']

pattern

为了重复利用正则表达式,将表达式编译好,保存在pattern中,用法与re的方法基本一致。
pattern = re.compile(“d”)
pattern.search(“dog”)

Match

group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
span([group]) 方法返回 (start(group), end(group))。

时间

注意:datetime 类型是不可变对象

from datetime import datetime

# 构造datetime对象,参数代表:year,month,day,hour,minute,second
t = datetime(2019, 8, 6, 22, 30, 44)

# 获取当前时间(日期+时间点)
t = datetime.now()
print(t)

# 获取datetime对象中的日期
print(t.date())

# 获取datetime对象中的时间
print(t.time())

# 分别获取datetime对象中的属性
print(t.year)
print(t.month)
print(t.day)

# datetime对象 -> 字符串
print(t.strftime("%Y-%m-%d %H:%M:%S"))

# 字符串 -> datetime对象
print(datetime.strptime("2019-08-06", "%Y-%m-%d"))  # 第2个参数表示如何解析前面的字符串

# 字符串 -> 另一格式的字符串
time_ = datetime.strptime('20200420', "%Y%m%d")
print(time_.strftime('%Y-%m-%d %H:%M:%S'))

# 修改(产生新对象,因为t不可变)
b = t.replace(minute=50, second=30)

获取当前时间

注意:datetime 下的 time 与 time 模块不同

import time
print(time.time())# 返回的UTC时间,是从1970.1.1到现在的秒数
print(time.ctime(time.time())) # 接收一个以秒为单位的时间,然后转换成本地时间的字符串表示。
print(time.strftime("%Y-%m-%d %H:%M:%S"))

from datetime import datetime
print(datetime.now())

# 1565268398.010132
# Thu Aug  8 20:46:38 2019
# 2019-08-08 20:46:38
# 2019-08-08 20:46:38.010703

时间的运算

datetime 只能相减,得到 tiemdelta 对象:datetime.timedelta(m, n)表示相差m天n秒

tiemdelta可以相加减,也可以与datetime 相加减得到新的 datetime

格式化字符串

  • %y 两位数的年份表示(00-99)
  • %Y 四位数的年份表示(000-9999)
  • %m 月份(01-12)
  • %d 月内中的一天(0-31)
  • %H 24小时制小时数(0-23)
  • %I 12小时制小时数(01-12)
  • %M 分钟数(00=59)
  • %S 秒(00-59)
  • %F %Y-%m-%d的简写(2019-08-06)
  • %D %m/%d/%y的简写(08/06/19)
  • %a 本地简化星期名称
  • %A 本地完整星期名称
  • %b 本地简化的月份名称
  • %B 本地完整的月份名称
  • %c 本地相应的日期表示和时间表示
  • %j 年内的一天(001-366)
  • %p 本地A.M.或P.M.的等价符
  • %U 一年中的星期数(00-53)星期天为星期的开始
  • %w 星期(0-6),星期天为星期的开始
  • %W 一年中的星期数(00-53)星期一为星期的开始
  • %x 本地相应的日期表示
  • %X 本地相应的时间表示
  • %z UTC 时区偏置,格式为+HHMM或-HHMM;如果是简单时区则为空
  • %Z 当前时区的名称
  • %% %号本身

tqdm

https://pypi.org/project/tqdm/#parameters

tqdm(self, iterable=None, desc=None, total=None, leave=True,file=None, ncols=None, mininterval=0.1,maxinterval=10.0, miniters=None, ascii=None, disable=False,unit='it', unit_scale=False, dynamic_ncols=False,smoothing=0.3, bar_format=None, initial=0, position=None,postfix=None, unit_divisor=1000):
  • desc:progressbar的前缀
  • leave : 默认True,结束后保留进度条
  • ascii:默认 False,如果True,进度条将以“123456789#”显示,而不是实线
  • ncols:整个消息的长度

设置提示消息

pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
    time.sleep(0.25)
    pbar.set_description("Processing %s" % char)

手动控制

with tqdm(total=100) as pbar:
    for i in range(10):
        time.sleep(0.1)
        pbar.update(10) # 每次进度增加10

tqdm读取文件

from tqdm import tqdm
import codecs as cs

with tqdm(cs.open("1.txt"),desc = "status: ") as pbar:
    for i in pbar:
        b+=1
        if b % 1000 == 0:
            pbar.update(1000)
print b

多重进度条

Screenshot-Jupyter2

除了 tqdm 构造函数之外,还有下面的构造函数可以用

`python
class tqdm(xrange(args), **kwargs)
def trange(
args, kwargs):
“””
A shortcut for tqdm(xrange(*args),
kwargs).
On Python3+ range is used instead of xrange.
“””

class tqdm_gui(tqdm):
def tgrange(*args, **kwargs):
“””
Experimental GUI version of trange!
“””

def tnrange(*args, **kwargs):
class tqdm_notebook(tqdm):
“””
Experimental IPython/Jupyter Notebook widget using tqdm!
“””


### sys

用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:Python解释器。

sys.argv #命令行参数List,第一个元素是程序本身路径
sys.modules.keys() #返回所有已经导入的模块列表
sys.exc_info() #获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息
sys.exit(n) #程序,正常退出时exit(0)
sys.hexversion #获取Python解释程序的版本值,16进制格式如:0x020403F0
sys.version #获取Python解释程序的版本信息
sys.maxint #最大的Int值
sys.maxunicode #最大的Unicode值
sys.modules #返回系统导入的模块字段,key是模块名,value是模块
sys.path #返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform #返回操作系统平台名称
sys.stdout #标准输出
sys.stdin #标准输入
sys.stderr #错误输出
sys.exc_clear() #用来清除当前线程所出现的当前的或最近的错误信息
sys.exec_prefix #返回平台独立的python文件安装的位置
sys.byteorder #本地字节规则的指示器,big-endian平台的值是’big’,little-endian平台的值是’little’
sys.copyright #记录python版权相关的东西
sys.api_version #解释器的C的API版本
sys.version_info #获取Python解释器的版本信息
sys.getwindowsversion #获取Windows的版本
sys.getdefaultencoding #返回当前你所用的默认的字符编码格式
sys.getfilesystemencoding #返回将Unicode文件名转换成系统文件名的编码的名字
sys.setdefaultencoding(name) #用来设置当前默认的字符编码
sys.builtin_module_names #Python解释器导入的模块列表
sys.executable #Python解释程序路径
sys.stdin.readline #从标准输入读一行,sys.stdout.write(“a”) 屏幕输出a


### os

#### 文件操作

```python
os.remove()       #删除文件 
os.rename()       #重命名文件 

目录操作

os.chdir()                   #改变目录 
os.mkdir/makedirs()   #创建目录/多层目录 
os.rmdir/removedirs   #删除目录/多层目录 
os.listdir()               #列出目录下的文件名(不递归)
os.walk()                   #列出目录下的所有文件名(递归)

os.mkdiros.makedirs的差别在于 os.makedirs 会递归地去建立目录,也就是说连同中继的目录也会一起建立,就类似于 Linux 中的 mkdir -p

>>> import os
>>> os.mkdir('foo/bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 2] No such file or directory: 'foo/bar'
>>> os.makedirs('foo/bar')

使用 os.mkdir时,如果你给定的 path 参数是个多层的 path,如果某个中继的目录不存在(比如说上例中的 foo), Python 将会报错.

但如果使用 os.makedirs 则 Python 会连同中间的目录一起建立.但有一点值得注意,当 path 末端的目录已经存在的话,os.makedirs 也是会引发例外.

os.path

https://docs.python.org/3/library/os.path.html#os.path.dirname

os模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的。

路径操作

os.getcwd()                   # 取得当前工作目录 
os.path.abspath(path)        # 获取文件、目录的绝对路径
os.path.basename()         # 文件名 ,去掉目录路径
os.path.dirname()         # 目录路径 ,去掉文件名
# dirname 与 basename 组成完整的文件路径(绝对、相对路径都可以)

os.path.join()              # 将分离的各部分组合成一个路径名 
os.path.split(path)     # 返回(dirname(),basename())元组 
# 将路径名*path*分割为(head, tail) , *tail* 路径名的最后部分,绝对不包含分隔符(/)  *head* 是 tail 之前的路径。如果*path* 以(/) 结尾, 那么*tail* 为空 

os.path.splitdrive(path)# 返回(盘符、远程地址,路径)元组
os.path.splitext(path)    # 返回(剩余部分,扩展名)元组

os.path.commonpath(paths)     #返回公共的父节点路径(有效路径)
os.path.commonprefix(list) #返回公共的路径前缀(字符串匹配,不一定是有效路径)
# commonprefix(['/usr/lib', '/usr/local/lib'])
# '/usr/l'
# commonpath(['/usr/lib', '/usr/local/lib'])
# '/usr'

os.path.realpath(path)     #返回真实路径,消除符号链接,类似于abspath
os.path.relpath(path, start=os.curdir)    #返回相对于指定的start的相对路径,默认是当前目录

os.path.exists(path)        如果path存在,返回True;如果path不存在,返回False。
os.path.isabs(path)     如果path是绝对路径,返回True。
os.path.isfile(path)      如果path是一个存在的文件,返回True。否则返回False。
os.path.isdir(path)     如果path是一个存在的目录,则返回True。否则返回False。
os.path.join(path1[, path2[, ...]])     将多个路径组合后返回,第一个绝对路径之前的参数将被忽略。

os.path.normcase(path)      在Linux和Mac平台上,该函数会原样返回path,在windows平台上会将路径中所有字符转换为小写,并将所有斜杠转换为饭斜杠。  
os.path.normpath(path)      规范化路径。

os.path.expanduser(path)# 将路径中的~转义为真实的home目录地址,否则不做变化
os.path.expandvars(path)# 将路径中的环境变量转义为真实的值,否则不做变化

os.path.normcase(path)

返回大小写正常化后的路径名。

对于 Mac、Unix,该操作没有效果(他们对a.txt,A.txt视为同一名称)

对于不区分大小写的文件系统,会将路径转为小写;

对于 window,前向斜杆\ 会转为后向斜杆/

文件判断

os.path.getatime\ctime\mtime       # 分别返回最近访问、创建、修改时间 
os.path.isfile(path)                  # 是否为文件
os.path.isdir(path)                      # 是否为目录
os.path.getsize()                         # 返回文件大小 
os.path.exists(path)                  # 是否存在 
os.path.isabs()                              # 是否为绝对路径 
os.path.islink()                                # 判断是否为连接符号,获取真实路径请看上面的realpath函数
os.path.samefile(path1, path2)    # 是否是同一个文件
os.path.sameopenfile(fp1, fp2)    # 是否指向同一个文件

configparser

import configparser
import os

#实例化ConfigParser
cf = configparser.ConfigParser()

#获取当前的绝对路径
current_path = os.path.abspath(__file__)
#当前文件的目录
now_cig = os.path.dirname(current_path)
#拼接配置文件路径
con_cig = os.path.join(now_cig + "/config/config.ini")
#读取配置文件
cf.read(con_cig)

#打印配置文件里面section名为"people"里面的options
print(cf.options(section='people'))
#打印配置文件里面section里面的某个potions的value
print(cf.get('people','name'))

#加添section
cf.add_section('cc')
#设置指定section的key=value
cf.set('cc','aa','bb')
print(cf.options(section='cc'))

shutil

https://docs.python.org/3/library/shutil.html#shutil.disk_usage

从文件对象拷贝

copyfileobj(fsrc, fdst[, length])

# with 可以同时 支持 多个上下文管理器
with open("./1.txt",encoding='utf8') as f1, open('./2,txt','w',encoding='utf8') as f2:
    su.copyfileobj(f1,f2)

文件操作

复制

copyfile(src, dst, *, follow_symlinks=True)

从 src复制的文件内容到 dst 文件中,只复制内容,不包含元数据

dst 必须是目标文件名,而不是目录

copy(src, dst, *, follow_symlinks=True*)

复制文件数据、权限数据;其他的元数据(创建时间、修改时间)没有保留

dst允许是目录,或者文件名

copy2(src, dst, *, follow_symlinks=True)

与 copy 一样,除了会尽量保存文件的元数据

移动(文件/目录)

move(src, dst, copy_function=copy2)

将文件或者目录复制到 dst

目录操作

复制

copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)

将递归地将整个目录文件复制到 dst,dst 必须不存在

例子:跳过指定的文件

from shutil import copytree, ignore_patterns

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

利用 ignore 进行日志记录功能

from shutil import copytree
import logging

def _logpath(path, names):
    logging.info('Working in %s', path)
    return []   # nothing will be ignored

copytree(source, destination, ignore=_logpath)
移动

参考 move

删除

rmtree(path, ignore_errors=False, onerror=None)

删除整个目录,path 必须指向目录 (不可以是指向目录的符号链接).

例子:处理只读的文件,尝试删除

import os, stat
import shutil

def remove_readonly(func, path, _):
    "清除 readonly bit 并重新尝试删除"
    os.chmod(path, stat.S_IWRITE)
    func(path)

shutil.rmtree(directory, onerror=remove_readonly)
ignore_patterns

This factory function creates a function that can be used as a callable for copytree()’s ignore argument, ignoring files and directories that match one of the glob-style patternsprovided.

文件状态操作

复制文件权限

copymode(src, dst, *, follow_symlinks=True)

从 src 复制 permission bits 到 dst。文件内容、拥有者、组都不受影响

复制文件状态

copystat(src, dst, *, follow_symlinks=True)

从 src 复制 permission bits、 last access time、last modification time、 flags 到 dst. 在 linux 中,还会尝试复制 “extended attributes”

文件内容、拥有者、组都不受影响

chown

chown(path, user=None, group=None)

修改 path 的用户或者组

其他

磁盘使用情况

disk_usage(path)

返回磁盘的使用情况统计结果元组:total, used, free, 单位是 bytes.

which

which(cmd, mode=os.F_OK | os.X_OK, path=None)

查看命令的执行程序名称

shutil.which("python")
# '/Users/jizhongxian/anaconda3/bin/python'

Archiving operations(压缩包操作)

用到再看

https://docs.python.org/3/library/shutil.html#archiving-operations

glob

glob 规则:http://www.man7.org/linux/man-pages/man7/glob.7.html

最常用的通配符是 *、?、[]

通配符 描述 例子 匹配 不匹配
* 匹配任意数量的字符包括空字符 Law* Law, Laws, or Lawyer
*Law* Law, GrokLaw, or Lawyer.
? 匹配任意一个字符 ?at Cat, cat, Bat or bat at
[abc] 匹配任意一个包含的字符 [CB]at Cat or Bat cat or bat
[a-z] 匹配任意一个给定范围的字符 Letter[0-9] Letter0, Letter1 etc. Letters or Letter
** 匹配任意的目录(包括当前目录) */\.js ss.js, a/hh.js, a/b/c.js

在Linux和POSIX系统中[…]的扩展

通配符 描述 例子 匹配 不匹配
[!abc] 不匹配任意一个包含的字符 [!C]at Bat, bat, or cat Cat
[!a-z] 不匹配任意一个给定范围的字符 Letter[!3-5] Letter1, Letter2 etc. Letter3, Letter4 or Letter5

与正则的比较:

Glob的通配符 等价正则的表达式
? .
* .*

注意事项

  • Glob尝试匹配整个字符串,而不是片段S*.DOC将匹配S.DOC和SA.DOC,但不匹配POST.DOC或SURREY.DOCKS,正则只匹配子串除非使用^$。所以S*.DOC的等价正则是^S.*\.DOC$
  • 路径分隔符(unix的/,windows的\)不会被? *匹配。如果要匹配,需要用**匹配任意层级的目录(包括当前目录) **/*.js ==> a/b/c.js
  • [^...]是无效的
  • .开头的文件被 glob 视为特殊的文件,*匹配不到他,需要显式处理
    >>> import glob
    >>> glob.glob('*.gif')
    ['card.gif']
    >>> glob.glob('.c*') #显式地指定.
    ['.card.gif']
    

glob

glob.glob(pathname, *, recursive=False)

返回符合 pathname 模式的路径列表,recursive会递归地查找

import glob
glob.glob('./[0-9].*')
# ['./1.gif', './2.txt']
glob.glob('*.gif')
# ['1.gif', 'card.gif']
glob.glob('?.gif')
# ['1.gif']
glob.glob('**/*.txt', recursive=True)
# ['2.txt', 'sub/3.txt']
glob.glob('./**/', recursive=True)
# ['./', './sub/']

iglob

glob.iglob(pathname, *, recursive=False)

与 glob 作用相同,只不过返回的一个迭代器

escape

glob.escape(pathname)

转义所有的字符('?', '*' and '[')。

比如escape('//?/c:/Quo vadis?.txt') 返回 '//?/c:/Quovadis[?].txt'.

fnmatch

Pattern Meaning
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any character not in seq

('/' on Unix) .开头的文件,不是特殊文件

fnmatch

  • fnmatch.fnmatch(filename, pattern)

测试 filename 是否匹配 pattern 字符串, 参数都是用 os.path.normcase()规范过了。 fnmatchcase() 用于 大小写敏感的比较, 不论那是否是该操作系统的标准

import fnmatch
import os

for file in os.listdir('.'):
    if fnmatch.fnmatch(file, '*.txt'):
        print(file)

fnmatchcase

  • fnmatch.fnmatchcase(filename, pattern)
    大小写敏感的比较,函数中不使用os.path.normcase().

filter

  • fnmatch.filter(names, pattern)
    返回列表 names 中符合 pattern 的子列表,等价于 [n for n in namesif fnmatch(n, pattern)], 但内部更进行了高效地实现。

translate

  • fnmatch.translate(pattern)
    将 shell-风格的 pattern 转为正则表达式 re.match().

    import fnmatch, re
    
    regex = fnmatch.translate('*.txt')
    print(regex)
    # '(?s:.*\\.txt)\\Z'
    reobj = re.compile(regex)
    reobj.match('foobar.txt')
    # <re.Match object; span=(0, 10), match='foobar.txt'>
    

评论