python内置模块(二)

关于datetime/time/commands模块的内容可以点击python内置模块查看。

subprocess

subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/错误,以及获得它们的返回值。

getoutput(cmd)

该命令类似commands模块中的getoutput(),执行cmd命令返回执行结果。

1
2
3
4
5
6
7
>>> PIDS = subprocess.getoutput("netstat -aon | findstr 0:80")
>>> print(PIDS)
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4
>>> PIDS1 = subprocess.getoutput("netstat -aon | grep 0:80")
>>> print(PIDS1)
'grep' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

getstatusoutput(cmd)

该命令类似commands模块中的getstatusoutput(),执行cmd命令返回包含2个元素的元组。
第一个元素为命令执行状态(int),如果执行成功返回0,不成功返回非0。
第二个元素为命令执行结果(str)。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import subprocess
>>> PIDS = subprocess.getstatusoutput("netstat -aon | findstr 0:80")
>>> print(PIDS) #输出结果为元组
(0, ' TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4\n TCP 192.168.0.102:64793 111.202.100.60:80 TIME_WAIT 0')
>>> PIDS1 = subprocess.getstatusoutput("netstat -aon | grep 0:80")
>>> print(PIDS1)
(255, "'grep' 不是内部或外部命令,也不是可运行的程序\n或批处理文件。")
>>> status, result = subprocess.getstatusoutput("netstat -aon | grep 0:80") #python中典型使用方法
>>> print(status)
255
>>> print(result)
'grep' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

call()

参数说明

1
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

执行命令并返回执行状态,其中shell参数为False时,命令需要以列表的方式传入,当shell为True时,可直接传入命令。默认情况下shell=False
shell=False情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> import subprocess
>>> a = subprocess.call("ls") #单个不带参数的命令可直接执行
anaconda-ks.cfg
>>> print(a) #命令执行结果
0
>>> b = subprocess.call("ls -l") #带参数命令直接传入将会报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/subprocess.py", line 524, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
>>> b = subprocess.call(["ls", "-l"]) #带参数命令以列表方式传入
total 4
-rw-------. 1 root root 2523 Apr 21 2016 anaconda-ks.cfg
>>> print(b)
0

shell=True情况

1
2
3
4
5
6
>>> import subprocess
>>> a = subprocess.call("ls -l", shell=True) #带参数命令也可直接传入
total 4
-rw-------. 1 root root 2523 Apr 21 2016 anaconda-ks.cfg
>>> print(a)
0

check_call()

参数说明

1
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

执行命令,若返回状态码为0,则返回0,否则抛出异常CalledProcessError
注意:该方法等价于python3.5中的run(..., check=True)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> import subprocess
>>> a = subprocess.check_call(["ls", "-l"])
total 4
-rw-------. 1 root root 2523 Apr 21 2016 anaconda-ks.cfg
>>> print(a)
0
>>> a = subprocess.check_call("ls -l", shell=True)
total 4
-rw-------. 1 root root 2523 Apr 21 2016 anaconda-ks.cfg
>>> print(a)
0
>>> b = subprocess.check_call("exit 1", shell=True) #即使正确执行命令,但返回值不为0抛出异常
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/subprocess.py", line 542, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

check_output()

语法说明

1
args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None

执行命令,若返回状态码为0,则返回执行结果,否则抛出异常CalledProcessError
注意:该方法等价于python3.5中的run(..., check=True, stdout=PIPE).stdout

1
2
3
4
5
6
7
8
9
10
11
12
>>> import subprocess
>>> a = subprocess.check_output("ls -l", shell=True)
>>> print(a) #输出为执行结果
total 4
-rw-------. 1 root root 2523 Apr 21 2016 anaconda-ks.cfg

>>> b = subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

run()

python 3.5添加的函数。
语法说明:

1
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)

执行指定命令,等待命令执行完成后返回一个包含执行结果的CompleteProcess类的实例。

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
>>> subprocess.run("dir", shell=True)
驱动器 C 中的卷没有标签。
卷的序列号是 A001-9D89

C:\Users\xiaohuihui 的目录

2018/04/19 20:30 <DIR> .
2018/04/19 20:30 <DIR> ..
2017/11/17 10:16 <DIR> .android
............................................
...........................................
2018/01/23 16:23 0 2.txt
2018/04/16 06:45 <DIR> 3D Objects
2018/04/13 20:28 4 bacon.txt
8 个文件 1,029,964,132 字节
24 个目录 94,803,804,160 可用字节
CompletedProcess(args='dir', returncode=0)
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\xiaohuihui\AppData\Local\Programs\Python\Python36\lib\subprocess.py", line 418, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1.
>>> subprocess.run("netstat -aon|findstr 0:80", shell=True, stdout=subprocess.PIPE)
CompletedProcess(args='netstat -aon|findstr 0:80', returncode=0, stdout=b' TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4\r\n')

参数说明

subprocess中的call()check_call()check_output()以及run()参数列表已经列出,下面是参数的说明

  • args
    要执行的shell命令,默认是一个字符串序列,如['df', '-hT']('df', '-hT'),也可以是一个字符串,如'df -hT',但此时需要把shell参数的值设置为True
  • shell
    如果shell为True,那么指定的命令将通过shell执行。如果需要访问某些shell特性,如管道、文件名通配符等,这将非常有用。
  • check
    如果check参数的值是True,且执行命令的进程以非0的状态码退出,则会抛出一个CalledProcessError异常,且该异常对象会包含参数、退出状态码以及stdout和stderr(若被捕获)。
  • stdout/stderr
    程序的标准输出和错误输出。
  • run()函数默认不会捕获命令执行结果的正常输出和错误输出,如果我们想获取这些内容,需要传递subprocess.PIPE然后可以通过返回的CompleteProcess类实例的stddout和stderr属性捕获相应的内容。
  • call()和check_call()函数返回的是命令执行的状态码而不是CompleteProcess类实例,所以它们的stdout和stderr不适合赋值为subprocess.PIPE
  • check_output()函数默认会返回执行结果,所以不用设置stdout的值,如果希望在结果中捕获错误信息,可以设置stderr = subprocess.STDOUT
  • cwd
    用于设置子进程的当前目录。当它不为None时,子程序在执行前,它的当前路径会被替换成cwd的值。这个路径并不会被添加到可执行程序的搜索路径,所以cwd不能是相对路径。
  • input
    该参数是传递给Popen.communicate(),通常该参数的值必须是一个字节序列,如果universal_newline=True,则其值应该是一个字符串。
  • universal_newline
    该参数影响的是输入输出的数据格式,默认为False,此时stdout和stderr的输出是字节序列,设置为True时stdout和stderr的输出是字符串。

CompleteProcess类说明

subprocess.CompleteProcess类在python3.5中才存在,表示一个已经结束进程的状态信息,包含的属性如下

  • args:用于加载进程的参数,可能是一个列表或者一个字符串。
  • returncode:子进程的退出状态码,通常情况下状态码为0表示进程成功运行;负值-N表示子进程被信号N终止。
  • stdout:从子进程捕获的stdout。这通常是一个字节序列,如果run()函数被调用时指定universal_newlines=True,则该属性值是一个字符串。如果run()函数被调用时指定stderr=subprocess.STDOUT,那么stdout和stderr将会被整合到这一个属性中,且stderr将会为None
  • stderr:从子进程捕获的stderr。它的值与stdout一样,是一个字节序列或一个字符串。如果stderr没有被捕获的话,它的值就为None
  • check_returncode(): 如果returncode是一个非0值,则该方法会抛出一个CalledProcessError异常。

Popen

该类用于在一个新的进程中执行一个子程序。上面介绍的函数都是基于subprocess.Popen类实现的,通过使用这些被封装后的高级函数可以很方便的完成一些常见的需求。当无法通过上面的高级函数实现一些不太常用的功能时,可以通过subprocess.Popen来完成。
示例1

1
2
3
4
>>> import subprocess
>>> p = subprocess.Popen("netstat -aon|findstr 0:80", shell=True, stdout=subprocess.PIPE)
>>> print(p.stdout.read())
b' TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4\r\n'

示例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write('print(1) \n') #返回写入的字符数
10
>>> obj.stdin.write('print(2) \n')
10
>>> obj.stdin.write('print(3) \n')
10
>>> out,err = obj.communicate()
>>> print(out)
1
2
3

>>> print(err)

总结

  1. Python2.4版本引入了subprocess模块用来替换os.system()、os.popen()、os.spawn*()等函数以及commands模块;也就是说如果你使用的是Python 2.4及以上的版本就应该使用subprocess模块了。
  2. 如果你的应用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用。
  3. 如果你的应用使用的是Python 3.5及以上的版本,Python官方给出的建议是尽量使用subprocess.run()函数。
  4. 当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能。

更多关于subprocess说明可点击查看官方文档。

os

os模块提供对操作系统的文件目录操作、文件路径操作等功能。

os.path

os.path模块主要用于对文件路径的操作,如:路径分割和拼接、取文件相对路径和绝对路径等。

  • os.path.abspath(path)
    返回指定文件的绝对路径。

    1
    2
    3
    >>> import os
    >>> os.path.abspath("sunny.txt")
    'C:\\Users\\xiaohuihui\\sunny.txt'
  • os.path.split(path)
    将路径名称分割成两部分(head,tail),tail是路径path名称中最后一部分且不包括斜线,head是tail之前的所有部分。如果path以斜线结尾则tail为空,如果path中没有斜线则head为空字符串。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import os
    >>> os.path.split("C:\\Users\\xiaohuihui")
    ('C:\\Users', 'xiaohuihui')
    >>> os.path.split("C:\\Users\\xiaohuihui\\")
    ('C:\\Users\\xiaohuihui', '')
    >>> os.path.split("C:\\Users\\xiaohuihui\\sunny.txt")
    ('C:\\Users\\xiaohuihui', 'sunny.txt')
    >>> os.path.split("sunny.txt")
    ('', 'sunny.txt')
  • os.path.splitext(path)
    将路径名称分割成两部分(root,ext),其中ext为后缀名。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import os
    >>> os.path.splitext("C:\\Users\\xiaohuihui\\sunny.txt")
    ('C:\\Users\\xiaohuihui\\sunny', '.txt')
    >>> os.path.splitext("C:\\Users\\xiaohuihui\\")
    ('C:\\Users\\xiaohuihui\\', '')
    >>> os.path.splitext("C:\\Users\\xiaohuihui")
    ('C:\\Users\\xiaohuihui', '')
    >>> os.path.splitext("sunny.text")
    ('sunny', '.text')
  • os.path.basename(path)
    返回path路径名的基名称,也就是os.path.split(path)返回的第二个值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import os
    >>> os.path.basename("C:\\Users\\xiaohuihui\\sunny.txt")
    'sunny.txt'
    >>> os.path.basename("C:\\Users\\xiaohuihui\\")
    ''
    >>> os.path.basename("C:\\Users\\xiaohuihui")
    'xiaohuihui'
    >>> os.path.basename("sunny.txt")
    'sunny.txt'
  • os.path.dirname(path)
    返回path路径的目录名称,也就是os.path.split(path)返回的第一个值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import os
    >>> os.path.dirname("C:\\Users\\xiaohuihui\\sunny.txt")
    'C:\\Users\\xiaohuihui'
    >>> os.path.dirname("C:\\Users\\xiaohuihui\\")
    'C:\\Users\\xiaohuihui'
    >>> os.path.dirname("C:\\Users\\xiaohuihui")
    'C:\\Users'
    >>> os.path.dirname("sunny.txt")
    ''
  • os.path.join(path, *paths)
    将一个或多个路径中的非空值通过路径分隔符拼接成一个新的路径名称,如果在拼接过程中遇到绝对路径将会丢弃前面的部分并从该绝对路径重新开始拼接。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> import os
    >>> os.path.join("C:\\Users\\xiaohuihui\\")
    'C:\\Users\\xiaohuihui\\'
    >>> os.path.join("C:\\Users\\xiaohuihui")
    'C:\\Users\\xiaohuihui'
    >>> os.path.join("C:\\Users\\xiaohuihui", "sunny.txt")
    'C:\\Users\\xiaohuihui\\sunny.txt'
    >>> os.path.join("C:\\Users", "xiaohuihui", "sunny.txt")
    'C:\\Users\\xiaohuihui\\sunny.txt'
    >>> os.path.join("C:\\Users", "C:\\Users\\xiaohuihui", "sunny.txt")
    'C:\\Users\\xiaohuihui\\sunny.txt'
  • os.path.exists(path)
    指定的文件路径存在则返回True,否则返回False。如果是失效的链接文件则返回False。

    1
    2
    3
    4
    5
    6
    7
    >>> import os
    >>> os.path.exists("C:\\Users\\xiaohuihui\\")
    True
    >>> os.path.exists("C:\\Users\\xiaohuihui\\www.txt")
    False
    >>> os.path.exists("C:\\Users\\xiaohuihui\\sunny.txt")
    True
  • os.path.getatime(path)
    返回该路径对应文件的最后一次访问时间的时间戳(秒),如果文件不存在或无法访问则引发OSError

    1
    2
    3
    4
    5
    >>> import os
    >>> os.path.getatime("C:\\Users\\xiaohuihui\\sunny.txt")
    1523624105.3170362
    >>> os.path.getatime("C:\\Users\\xiaohuihui")
    1524141055.6605625
  • os.path.getmtime(path)
    返回该路径对应文件的最后修改时间的时间戳(秒),如果文件不存在或无法访问则引发OSError

    1
    2
    3
    4
    5
    >>> import os
    >>> os.path.getmtime("C:\\Users\\xiaohuihui\\sunny.txt")
    1523627463.3876014
    >>> os.path.getmtime("C:\\Users\\xiaohuihui")
    1524141055.6605625
  • os.path.getctime(path)
    返回该路径对应文件的ctime,在某些系统上(unix)是最后一次元数据更改时间,其他系统上是(如windows)是路径创建时间;,如果文件不存在或无法访问则引发OSError

    1
    2
    3
    4
    5
    >>> import os
    >>> os.path.getctime("C:\\Users\\xiaohuihui\\sunny.txt")
    1523624105.3170362
    >>> os.path.getctime("C:\\Users\\xiaohuihui")
    1508831681.0998952
  • os.path.getsize(path)
    返回指定路径对应文件的字节大小

    1
    2
    3
    4
    5
    6
    7
    >>> import os
    >>> os.path.getsize("C:\\Users\\xiaohuihui\\sunny.txt")
    68
    >>> os.path.getsize("C:\\Users\\xiaohuihui\\")
    20480
    >>> os.path.getsize("C:\\Users\\xiaohuihui")
    20480
  • os.path.relpath(path, start=os.curdir)
    返回path相对于start的相对路径

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> import os
    >>> os.path.relpath("C:\\Users\\xiaohuihui\\sunny.txt")
    'sunny.txt'
    >>> os.path.relpath("C:\\Users\\xiaohuihui\\")
    '.'
    >>> os.path.relpath("C:\\Users\\xiaohuihui")
    '.'
    >>> os.path.relpath("C:\\Users\\xiaohuihui\\sunny.txt", start="C:\\Users")
    'xiaohuihui\\sunny.txt'
  • os.path.realpath(path)
    获取path的真实、绝对路径(可用于获取软链接文件指向的文件路径)

    1
    2
    3
    >>> import os
    >>> os.path.realpath("sunny.txt")
    'C:\\Users\\xiaohuihui\\sunny.txt'
  • os.path.isabs(path)
    判断path是否为绝对路径,是则返回True,否则返回False。

    1
    2
    3
    4
    5
    >>> import os
    >>> os.path.isabs("C:\\Users\\xiaohuihui\\sunny.txt")
    True
    >>> os.path.isabs("sunny.txt")
    False
  • os.path.isfile(path)
    判断path是否是一个文件

    1
    2
    3
    4
    5
    6
    7
    >>> import os
    >>> os.path.isfile("C:\\Users\\xiaohuihui\\sunny.txt")
    True
    >>> os.path.isfile("sunny.txt")
    True
    >>> os.path.isfile("C:\\Users\\xiaohuihui\\")
    False
  • os.path.isdir(path)
    判断path是否是一个目录

    1
    2
    3
    4
    5
    6
    7
    >>> import os
    >>> os.path.isdir("C:\\Users\\xiaohuihui\\sunny.txt")
    False
    >>> os.path.isdir("C:\\Users\\xiaohuihui\\")
    True
    >>> os.path.isdir("C:\\Users\\xiaohuihui")
    True
  • os.path.islink(path)
    判断path是否是一个链接

    1
    2
    3
    >>> import os
    >>> os.path.islink("C:\\Users\\xiaohuihui\\sunny.txt")
    False
  • os.path.ismount(path)
    判断path是否是一个挂载点

    1
    2
    3
    4
    5
    >>> import os
    >>> os.path.ismount("C:\\Users\\xiaohuihui\\sunny.txt")
    False
    >>> os.path.ismount("C")
    False
  • os.path.samefile(path1, path2)
    判断path1和path2是否为同一个文件

    1
    2
    3
    4
    5
    >>> import os
    >>> os.path.samefile("C:\\Users\\xiaohuihui\\sunny.txt", "sunny.txt")
    True
    >>> os.path.samefile("C:\\Users\\xiaohuihui\\sunny.txt", "sunny1.txt")
    False

os

在使用os模块过程中,在一些unix平台的许多文件或目录的操作函数支持下面的特性

  1. 指定一个文件描述符
    对于某些函数。path参数不仅可以是一个字符串,也可以是文件描述符。该函数会操作这个文件描述符引用的文件。可以通过os.supports_fd来检查当前平台的path参数是否可以指定为一个文件描述符,如果不可用将引发NotImplementedError。如果该函数还支持dir_fd或follow_symlinks参数,当path被以文件描述符的方式提供时,指定dir_fd或follow_symlinks参数是错误的。
  2. 相对于目录描述符的路径
    如果dir_fd不是None,它应该是一个指向某个目录的文件描述符,并且要操作的path应该是一个相对于该目录的相对路径;如果path是一个绝对路径,dir_fd将会被忽略。
  3. 不遵循符号链接
    如果follow_symlinks是False,并且要操作的路径中最后一个元素是一个符号链接时,该函数将会操作这个链接文件,而不是操作这个链接文件指向的文件。
  • os.access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True)
    测试当前用户是否对path所指向的文件有某种访问权限。
    mode可取值为:os.F_OK(文件存在)、os.R_OK(可读)、os.W_OK(可写)、os.X_OK(可执行)中的一个或用逻辑运算符‘|’连接起来的多个。

    1
    2
    3
    4
    5
    >>> import os
    >>> os.access("C:\\Users\\xiaohuihui\\sunny.txt",os.F_OK)
    True
    >>> os.access("C:\\Users\\xiaohuihui\\sunny.txt",os.R_OK|os.W_OK)
    True
  • os.chdir(path)
    更改当前工作目录

    1
    2
    3
    4
    5
    6
    >>> import os
    >>> os.getcwd()
    'C:\\Users\\xiaohuihui'
    >>> os.chdir("D:\\rhce")
    >>> os.getcwd()
    'D:\\rhce'
  • os.getcwd()
    返回一个表示当前目录的字符串

    1
    2
    3
    >>> import os
    >>> os.getcwd()
    'C:\\Users\\xiaohuihui'
  • os.listrdir(path=’.’)
    返回指定目录中所有的文件列表,顺序不固定,且不包含...,python2中path无默认值。

    1
    2
    3
    >>> import os
    >>> os.listdir("D:\Dns")
    ['1.txt', 'DNSTEST']
  • os.mkdir(path, mode=0777, *, dir_fd=None)
    创建一个名为path的目录并指定目录权限,如果目录已经存在则会引起FileExistsError;dir_fd是Python3.3开始新加的参数。
    需要说明的是该函数与os.makedirs()、os.mkfifo()函数创建的目或逛到文件的权限会受到umask的影响,比如指定mode为0777,实际目录权限为 0777 - umask = 0755

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> import os
    >>> os.path.exists("C:\\Users\\xiaohuihui\\test1") #判断test1目录是否存在
    False
    >>> os.mkdir("test1") #创建目录test1
    >>> os.path.exists("C:\\Users\\xiaohuihui\\test1")
    True
    >>> os.mkdir("test1")
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'test1'
  • os.remove(path, *, dir_fd=None)
    删除指定的文件,如果path是个目录将会引发OSError。

    1
    2
    3
    4
    5
    6
    >>> import os
    >>> os.path.exists("sunny1.txt")
    True
    >>> os.remove("C:\\Users\\xiaohuihui\\sunny1.txt")
    >>> os.path.exists("sunny1.txt")
    False
  • os.rmdir(path, *, dir_fd=None)
    删除指定的空目录,如果目录不为空会引发OSError。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> import os
    >>> os.path.exists("C:\\Users\\xiaohuihui\\test1")
    True
    >>> os.rmdir("test1")
    >>> os.path.exists("C:\\Users\\xiaohuihui\\test1")
    False
    >>> os.rmdir("oracle")
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    OSError: [WinError 145] 目录不是空的。: 'oracle'
  • os.rename(src, dst, *, src_dir_fd=-None, dst_dir_fd=None)
    目录或文件重命名,如果dst是一个目录将会引发OSError。在Unix平台上,如果dst存在且是一个文件,那么只要用户有权限就将会被静默替换;而在Windows平台上,如果dst存在,即使它是一个文件也会引发OSError。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> import os
    >>> os.path.exists("sunny1.txt")
    False
    >>> os.path.exists("sunny.txt")
    True
    >>> os.rename("sunny.txt", "sunny1.txt")
    >>> os.path.exists("sunny.txt")
    False
    >>> os.path.exists("sunny1.txt")
    True
  • os.replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
    与os.rename()功能相同,区别在于:对于os.replace()来说,如果dst存在且是一个文件,那么只要用户有权限就将会被静默替换,而没有平台上的差别

    1
    2
    3
    4
    5
    6
    >>> import os
    >>> os.replace("sunny1.txt","sunny.txt")
    >>> os.path.exists("sunny1.txt")
    False
    >>> os.path.exists("sunny.txt")
    True
  • os.linesep
    输出当前平台使用的行终止符。windows下使用的是\r\n,linxu下使用的是\n

    1
    2
    3
    4
    5
    >>> import os
    >>> os.linesep #windows下执行
    '\r\n'
    >>> os.linesep #linux下执行
    '\n'
  • os.name
    返回当前系统平台,windows则返回nt,unix则返回posix

    1
    2
    3
    4
    5
    >>> import os
    >>> os.name #windows下执行
    'nt'
    >>> os.name #linux下执行
    'posix'
  • os.system(cmd)
    执行指定命令并返回执行结果。

    1
    2
    3
    4
    >>> import os
    >>> os.system("netstat -aon|findstr 0:80")
    TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4
    0

知识点分享
在执行命令的时候,windows和unix的命令不尽相同,可以使用os.name进行区分,保证代码的兼容性。类似下面代码

1
2
3
4
5
6
7
8
9
10
11
if os.name == "nt":
cmd = "ipconfig"
elif os.name == "posix":
cmd = "ifconfig"

os.system(cmd)

>>> result = os.popen("netstat -aon|findstr 0:80").read()
>>> print(result)
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 4
TCP 10.12.5.244:57008 140.205.34.20:80 ESTABLISHED 32052

os是一个操作系统接口模块,提供了各种和操作系统相关的功能,上面写到的文件和目录操作等知识其中的一部分。更多更详细的内容可以点击Miscellaneous operating system interfaces查看官网介绍。

random

random是随机数操作模块,可以用来生成随机数和完成与随机数相关的功能。

  • random.random()
    用于生成半开区间[0.0, 1.0)内的一个随机浮点数。

    1
    2
    3
    import random
    >>> random.random()
    0.5716693670763958
  • random.uniform(a, b)
    用于生成一个指定范围内[a, b]的随机浮点数。

    1
    2
    3
    import random
    >>> random.uniform(10, 50)
    48.107294751423076
  • random.randint(a, b)
    用于生成一个指定范围内[a, b]的整数。

    1
    2
    3
    import random
    >>> random.randint(10, 50)
    30
  • random.randrange(start, stop[, step])
    用于从指定范围[start, stop)。按指定基数step递增的集合中获取一个随机数,step默认为1。
    random.randrange(stop)等价于random.randrange(0,stop)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import random
    >>> random.randrange(10, 50, 5)
    15
    >>> random.randrange(10, 50)
    22
    >>> random.randrange(50)
    42
    >>> random.randrange(50)
    28
  • random.choice(seq)
    从指定序列seq中随机获取一个元素。

    1
    2
    3
    4
    5
    import random
    >>> random.choice("abc1234")
    '2'
    >>> random.choice([1, 2, 3, 6, "a"])
    6
  • random.sample(population, k)
    从指定序列中随机抽取k个不重复的元素,并以列表的形式返回,用于不进行内容替换的随机抽样。

    1
    2
    3
    4
    5
    6
    7
    import random
    >>> list = [1, 2, 3, 4, 5, 6]
    >>> random.sample(list, 3)
    [2, 1, 3]
    >>> list1 = [1, 2, 2, 4, 5, 5]
    >>> random.sample(list1, 5)
    [5, 5, 2, 1, 2]
  • random.shuffle(x[, random])
    用于随机打乱一个列表中的元素,需要注意的是该函数操作的是列表对象,且没有返回值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import random
    >>> print(random.shuffle([1, 2, 3, 4, 5])) #该函数无返回值,直接给列表操作无效
    None
    >>> list = [1, 2, 3, 4, 5, 6]
    >>> random.shuffle(list) #传递的参数必须是列表对象。
    >>> print(list)
    [6, 3, 5, 2, 4, 1]
    >>> random.shuffle(list)
    >>> print(list)
    [1, 2, 4, 3, 6, 5]
    >>>

更多更详细的内容可以点击Generate pseudo-random numbers查看官网内容。

sys

sys模块提供访问由解释器使用或维护的变量和在与解释器交互使用到的函数。

  • sys.argv()
    给程序传递参数,其中argv[0]表示脚本名称。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import sys
    def usage():
    '''usage'''
    print('Usage: %s %s %s %s' % (sys.argv[0], 'tokenid', 'Subject', 'Content'))
    sys.exit()

    def main():
    if len(sys.argv) != 4:
    usage()
    else:
    print(sys.argv[0])
    print(sys.argv[1])
    print(sys.argv[2])
    print(sys.argv[3])

    if __name__ == "__main__":
    main()

输出结果

1
2
3
4
5
C:\Users\xiaohuihui>python D:/pythondev/calculate/module/sys1.py 12 22 32
D:/pythondev/calculate/module/sys1.py
12
22
32

  • sys.path
    获取指定模块模块搜索路径的字符串集合。将写好的模块放在得到的某个路径下,就可以在import的时候正确找到。在import模块名称的时候就是根据sys.path搜索模块。也可以自定义添加模块路径sys.path.append(path),但只是临时生效,退出当前环境之后失效。

    1
    2
    3
    import sys
    >>> sys.path
    ['', 'C:\\Users\\xiaohuihui\\AppData\\Local\\Programs\\Python\\Python36\\python36.zip', 'C:\\Users\\xiaohuihui\\AppData\\Local\\Programs\\Python\\Python36\\DLLs', 'C:\\Users\\xiaohuihui\\AppData\\Local\\Programs\\Python\\Python36\\lib', 'C:\\Users\\xiaohuihui\\AppData\\Local\\Programs\\Python\\Python36', 'C:\\Users\\xiaohuihui\\AppData\\Roaming\\Python\\Python36\\site-packages', 'C:\\Users\\xiaohuihui\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site-packages']
  • sys.modules
    sys.modules是一个全局字典,该字典在python启动之后就加载在内存中。当导入新模块时,sys.modules将自动记录该模块,第二次导入该模块时python会自动从字典中查找从而加快程序运行速度。它拥有字典的一切方法。

    1
    2
    3
    4
    5
    6
    7
    import sys
    >>> sys.modules.keys() #返回所有已导入的模块列表
    dict_keys(['builtins', 'sys', ...., 'os', 'errno', 'stat', '_stat', 'ntpath', 'genericpath', 'os.path', '_collections_abc', '_sitebuiltins', 'sysconfig', 'atexit'])
    >>> sys.modules.values() #返回模块(含对应路径)
    dict_values([<module 'builtins' (built-in)>, ...., <module 'atexit' (built-in)>])
    >>> sys.modules["os"] #指定key对应的values
    <module 'os' from 'C:\\Users\\xiaohuihui\\AppData\\Local\\Programs\\Python\\Python36\\lib\\os.py'>
  • sys.exit([arg])
    表示退出程序。
    一般情况下程序执行到末尾解释器自动退出,若需要中途退出,可以调用sys.exit()函数,带有一个可选的整数参数返回给调用它的程序。(0表示正常退出,其他表示异常)也可以使用字符串参数,传递对应的报错信息。

    1
    2
    3
    4
    import sys
    print("This exit test")
    sys.exit(1) # 退出程序
    print("there") # 不会被print

输出结果

1
This exit test

  • sys.stdin/stdout/stderr
    stdin/stdout/stderr变量包含与标准I/O流对应流对象。如果需要更好的控制输入输出,而print不能满足要求的情况下可以使用。
    print其实就是调用stdout.write(obj+'\n')方法。
    stdin示例
    1
    2
    3
    4
    import sys
    print("Please input your name: ")
    name = sys.stdin.readline() #和input功能类似。
    print("name:{0}".format(name))

输出结果

1
2
3
Please input your name: 
xiaohh
name:xiaohh

stdout示例

1
2
3
f = open("sunny2.txt", "w")
sys.stdout = f
print("hello world")

  • sys.platform
    获取当前系统平台,如win32/linux等。
    1
    2
    3
    4
    5
    import sys
    >>> sys.platform #windows系统执行
    'win32'
    >>> sys.platform #linux系统执行
    'linux'

判断系统平台执行不同命令,推荐使用下面方式

1
2
3
4
if sys.platform.startswith('freebsd'):
# FreeBSD-specific code here...
elif sys.platform.startswith('linux'):
# Linux-specific code here...

更多更详细的内容可以点击[System-specific parameters and functions]https://docs.python.org/3.6/library/sys.html)查看官网内容。

string

string模块主要是对字符串进行处理。

字符串常量

  • string.ascii_lowercase
    小写字母

    1
    2
    >>> string.ascii_lowercase
    'abcdefghijklmnopqrstuvwxyz'
  • string.ascii_uppercase
    大写字母

    1
    2
    >>> string.ascii_uppercase
    'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  • string.ascii_letters
    包含所有大小写字母

    1
    2
    >>> string.ascii_letters
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  • string.digits
    数字0到9的字符串。

    1
    2
    >>> string.digits
    '0123456789'
  • string.hexdigits
    包含十六进制所有字符的字符串

    1
    2
    >>> string.hexdigits
    '0123456789abcdefABCDEF'
  • string.octdigits
    包含八进制所有字符的字符串。

    1
    2
    >>> string.octdigits
    '01234567'
  • string.punctuation
    所有标点符号

    1
    2
    >>> string.punctuation
    '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
  • string.printable
    可打印的字符的字符串,包括数字、字母、标点符号和空格。

    1
    2
    >>> string.printable
    '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
  • string.whitespace
    空白字符,包括space, tab, linefeed(换行), return, formfeed(换页), and vertical tab。

    1
    2
    >>> string.whitespace
    ' \t\n\r\x0b\x0c'

字符串方法

  • string.capitalize()
    字符串首字母大写

    1
    2
    3
    >>> import string
    >>> print(s.capitalize())
    Hello world!
  • string.center(width)
    将原字符串用空格填充成一个长度为width的字符串,原字符串居中。
    下面原字符串hello world!长度为12,左面填充空格9个,右面填充空格8个。

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.center(29))
    hello world!
  • string.strip()
    去掉字符串两边的空格

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.center(30).strip())
    hello world!
  • string.count(s)
    返回字符串s在字符串中出现的次数

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.count("o"))
    2
  • string.isalnum()
    若字符串至少有一个字符且都是字母或数字则返回True,否则返回False

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.isalnum())
    False
  • string.isalpha()
    若字符串至少有一个字符并且都是字母则返回True,否则返回False

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.isalpha())
    False
  • string.isdigit()
    若字符串只包含数字则返回True,否则返回False

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.isdigit())
    False
  • string.isspace()
    若字符串中只包含空格,则返回True,否则返回False

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.isspace())
    False
  • string.istitle()
    若字符串是标题化的(单词首字母大写,其余小写)则返回True,否则返回False

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.istitle())
    False
  • string.title()
    返回标题华的字符串,即所有单词都是大写开始,其余字母均为小写。

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.title())
    Hello World!
  • string.partition(s)
    s将字符串分割成三个值

    1
    2
    3
    4
    >>> import string
    >>> s = "hello world!"
    >>> print(s.partition("o"))
    ('hell', 'o', ' world!')

字符串模板Template

通过string.Template可以为python定制字符串的替换标准。替换规则如下

  • $$将会被替换成$
  • $identifier定义了一个可替换的占位符,用来匹配identifier。默认情况下,identifier只能以下划线或者ASCII字符开头,并且区分大小写(除首字母外,其他部分可以使用数字)。
  • ${identifier}$identifier是等价的。当有效的标识符紧跟着占位符但不属于占位符时,需要使用{},例如${noun}ification

$之后出现非字符数字内容,将会出现ValueError异常信息。
Template类定义如下
class string.Template(template),参数是模板字符串。
提供2个方法

  • substitute(mapping, kwds)
    执行模板替换操作,返回一个新的字符串。
    mapping参数是一个类似字典的对象,keys和占位符名称一致。也可以提供关键字参数,其中关键字参数和占位符名称一致。
    mapping和`
    kwds都提供参数且重复的时候,将会优先选择**kwds`提供的占位符参数。
  • safe_substitute(mapping, kwds)
    mapping和`
    kwds提供的参数无法替换全部的占位符,使用substitute()会报ValueError错误,使用safe_substitute(),未被替换的占位符将会完整输出(不改变)。 同样,在$后的占位符出现非法字符,使用substitute()会报ValueError错误,使用safe_substitute()将会原样输出。 总之,使用safe_substitute()`将会返回一个可用的字符串,而不是抛出异常信息。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    >>> from string import Template
    >>> s = Template('$who like $what')
    >>> s.substitute(who='tim', what='kung pao')
    'tim like kung pao'
    >>> d = dict(who='tim')
    >>> Template('Give $who $100').substitute(d) #占位符以数字开头
    Traceback (most recent call last):
    ..........
    ValueError: Invalid placeholder in string: line 1, col 11
    >>> Template('$who like $what').substitute(d) #缺少key报错
    Traceback (most recent call last):
    ..........
    KeyError: 'what'
    >>> Template('$who like $what').safe_substitute(d) #缺少key正常输出
    'tim like $what'
    >>> Template('${who}likePython').substitute(who='I')
    'IlikePython'
  • Template高级用法
    通过继承string.Template,重写变量delimiter(定界符)和idpattern(替换格式),定制不同形式的模板。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import string

    template_text = ''' Delimiter : $de \n Replaced : %with_underscore \n Ingored : %notunderscored '''
    d = {'de': 'not replaced',
    'with_underscore': 'replaced',
    'notunderscored': 'not replaced'}

    class MyTemplate(string.Template): #继承自string.Template
    delimiter = '%' #定界符为%
    idpattern = '[a-z]+_[a-z]+' #替换模式为含有下划线

    print(string.Template(template_text).safe_substitute(d) ) #使用原有方法,定界符为$

    print(MyTemplate(template_text).safe_substitute(d)) #使用重写的方法,定界符为%

输出结果

1
2
3
4
5
6
7
Delimiter : not replaced 
Replaced : %with_underscore
Ingored : %notunderscored

Delimiter : $de
Replaced : replaced
Ingored : %notunderscored

字符串处理技巧

  1. 反转字符串

    1
    2
    3
    >>> s = '123456'
    >>> print(s[::-1])
    654321
  2. 字符串链接
    尽量使用join()链接字符串,使用+连接n个字符串需要申请n-1次内存,使用join()需要申请1次内存。

  3. 固定长度分割字符串

    1
    2
    3
    4
    >>> import re
    >>> s = '123456'
    >>> re.findall(r'.{1,3}', s) #使用正则
    ['123', '456']
  4. 使用()生成字符串

    1
    2
    3
    4
    5
    >>> sql = ('select count() from table '
    ... 'where id = "10" '
    ... 'group by sex')
    >>> print(sql)
    select count() from table where id = "10" group by sex

更多更详细的内容可以点击Common string operations查看官网内容。

logging

  1. 日志级别

下面列出的是日志级别及对应的值,当需要自定义日志级别及对应的值时,需要参考已经预先定义的级别及数值。
假如自定义的级别的数值和预先定义好的出现冲突,默认将会改写预定义的值,同时对应预定义的级别名称也失效。

级别 数字值 描述
CRITICAL 50 发生严重错误,导致应用程序不能继续运行
ERROR 40 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
WARNING 30 在某些不期望的事情发生时记录的信息,但是此时应用程序可以正常运行
INFO 20 信息详细程度仅次于DEBUG,通常只记录关键节点信息,确认程序按照预期运行
DEBUG 10 最详细的日志信息,典型应用场景是问题诊断
NOTSET 0 等同于DEBUG

上述对应的级别,从上到下日志输出量是越来越多,越来越详细。
当为某个应用程序指定一个日志级别之后,应用程序会记录所有日志级别大于或等于指定日志级别的日志信息,而不是仅仅记录指定级别的日志信息,小于该级别的日志记录将会被丢弃。

  1. 使用方式
    logging模块提供两种记录日志的方式
  • 第一种是使用logging提供的模块级别的函数
  • 第二种是使用logging日志系统的四大组件

其中logging提供的模块级别的函数也是对logging日志系统相关类的封装。
logging模块定义的模块级别的常用函数
函数|说明
-|:-:

更多更详细的内容可以点击Logging facility for Python查看官网内容。

Recommended Posts