Python3之标准库

一、操作系统接口

os模块提供了很多与操作系统相关联的函数;

导入os模块时建议使用 "import os" 风格而非 "from os import *"。原因是可以保证随操作系统变化而有所变化的 os.open() 函数不会覆盖内置函数 open();

内置的 dir() 和 help() 函数对使用 os 等大型模块时非常有用,dir()函数列出os模块的所有方法,help()方法用于说明os模块方法的使用;

Python 中使用 shutil 模块可实现文件或目录的复制、删除、移动;

二、shutil 模块实现文件或目录的复制、删除、移动

Python 中使用 shutil 模块可实现文件或目录的复制、删除、移动;

2.1、文件和文件夹复制

a)、shutil.copyfileobj(fsrc , fdst , length)

复制类文件(file-like)对象 fsrc 的内容到类文件对象 fdst。 可选整数参数 length,指定缓冲区大小。若length 的值为负数,复制操作不会将源数据分块进行复制。 默认的,为了避免不可控制的内存消耗,数据会被分块存入chunk中;

注意: 如果 fsrc 对象的当前文件位置不为 0 ,则只有从当前文件位置到文件末位的内容会被复制

b)、shutil.copyfile(src, dst)

复制文件 src 的内容(不包含元素据)到文件 dst 中, dst 必须是一个完整的目标文件。

源文件src 和目标文件 dst 不能为同一个文件,否则会报错

目标文件 dst 必须为可写状态,否则会触发 IOError

如果 dst 已经存在,则会被覆盖。

注意:字符设备、块设备和管道不能使用此方法复制。

使用字符串指定src 和 dst 路径。

C)、shutil.copymode(src, dst)

复制 src 的文件权限位到 dst 。文件的内容、属主和用户组不会受影响。

使用字符串指定src 和 dst 路径。

d)、shutil.copystat(src , dst)

复制文件 src 的文件权限位最后访问 access 时间最后修改 modification 时间和**标识 flags **到 dst

文件的内容、属主和用户组不会受影响。

使用字符串指定src 和 dst 路径。

e)、shutil.copy(src, dst)

复制文件 src 到 dst 文件或文件夹中。

如果 dst 是文件夹, 则会在文件夹中创建或覆盖一个文件,且该文件与 src 的文件名相同。

文件权限位会被复制。

使用字符串指定src 和 dst 路径。

f)、shutil.copy2(src, dst)

shutil.copy2(src , dst)函数相比较shutil.copy() 增加了复制文件的元数据功能

实际上,该方法是 shutil.copy() 和 shutil.copystat() 组合。

该方法相当于 Unix 命令的 ` cp -p `。

g)、shutil.ignore_patterns(*patterns)

该工厂函数创建了一个可以被调用的函数, 该函数可以用于 shutil.copytree() 的 ** ignore 参数**的值, 以跳过正确匹配的文件和文件夹

h)、shutil.copytree(src, dst, symlinks=False, ignore=None)

递归复制整个 src 文件夹

目标文件夹 dst 不能已经存在;shutil.copytree()方法会自动创建 dst 根文件夹。

文件夹权限和时间通过 shutil.copystat() 复制, 单独的文件通过 shutil.copy2() 复制。

如果“symlinks”为真, 源文件夹中的符号链接将会被保留,但是原链接的元数据不会被复制。如果值为假或被省略,则链接文件指向文件的内容和元数据复制到新文件夹树中。

如果指定了 ignore, 那么他必须是调用队列(callable),且作为 shutil.copytree() 的参数,参数包括文件夹本机及并通过 os.listdir()返回文件夹包含的内容。

由于 shutil.copytree() 递归复制,因此 ignore 会在复制每个子文件夹的时候被调用。

callable必须返回一个由当前文件夹下的文件夹和文件所组成的队列(i.e. a subset of the items in the second argument); 这些文件夹和文件在复制过程中会被忽略。

可以使用 shutil.ignore_patterns() 创建callable。

如果发生意外, shutil.Error() 返回错误原因。

2.2、文件/文件夹的删除和移动

a)、shutil.rmtree(path , ignore_errors , onerror)

删除整个目录树; 

path 必须指向一个文件夹,但不能是一个指向文件夹的符号链接;

如果 ` ignore_errors ` 值为真, 则删除失败时的信息将会被忽略。如果值为假或省略,那么这些错误将通过 onerror 指定的 handler 进行处理;

如果 onerror 被省略,则会 raise 一个异常。

如果指定了 onerror,则必须包含三个参数: function, path 和 excinfo的 callable 。 第一个参数 ` function ` , 该函数用于 raise 异常;该函数可以是 os.path.islink(), os.listdir(), os.remove(), os.rmdir()。 第二个参数 path 为传递给第一个参数的路径。 第三个参数 excinfo 为 sys.exc_info()返回的异常信息;

通过 onerror raise 的异常不会被捕捉;

b)、shutil.move(src, dst)

将一个文件或文件夹从 src 移动到 dst 。如果 dst 已存在且为文件夹,则 src 将会被移动到 dst内。 如果如 dst 存在但不是一个文件夹, 取决于 os.rename() 的语义,dst 可能会被覆盖。 如果 dst 与 src 在相同的文件系统下, 则使用 os.rename() 。 否认将使用 shutil.copy2() 复制 src到 dst 并删除;

c)、shutil.Error 

该异常汇集文件操作时 raise 的异常。 例如 shutil.copytree(), the exception argument is a list of 3-tuples (srcname, dstname, exception);

import os

# 输出当前工作目录
print("当前工作目录为:" , os.getcwd())
# 更改当前工作目录
os.chdir("/home/zx/ZX/MyProject/Python/Runoob/ZX_21_命名空间和作用域")
# 输出更新后工作目录
print("输出更新后工作目录:" , os.getcwd())

def mkfile(path):
    # 判断文件是否存在,存在则删除,不存在创建
    if os.path.exists(path):
        os.removedirs(path)
        print("文件删除成功")
    else:
        os.mkdir(path)
        print("文件创建成功")

path = "/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/file.txt"
mkfile(path)
当前工作目录为: /home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库
输出更新后工作目录: /home/zx/ZX/MyProject/Python/Runoob/ZX_21_命名空间和作用域
文件删除成功
import os
# 创建一个文件dir(os),用于存储dir(os)输出内容
file_dir = os.open("./file_dir(os)" , os.O_RDWR | os.O_CREAT)
for i in dir(os):
    os.write(file_dir , (i + '\n').encode("utf-8"))
os.close(file_dir)
import sys
import os
# 通过重定向,输出help(os)结果至文件
def WriteHelpFileByStdout(path ,mode , module):
    # 通过重定向,设置系统输出结果至文件路径path
    sys.stdout = open(path , mode)
    # 系统输出help(module)结果
    help(module)
    # 关闭文件
    sys.stdout.close()

path = './file_help(os)'
mode = 'w+'
module = os
WriteHelpFileByStdout(path ,mode , module)

 三、文件通配符

Python的glob模块可以实现查找符合特定规则的文件路径名功能

查找文件一般用到如下三个匹配符:”” 、“?” 、“[]”

” 匹配0个或多个字符;

”?” 匹配单个字符;

”[]” 匹配指定范围内的字符;如[0-9]匹配数字

3.1、glob.glob函数

以list的形式返回所有匹配的文件路径列表;

glob.glob函数只有pathname一个参数,定义了文件路径匹配规则,可以是绝对路径,也可以是相对路径;

3.2、glob.iglob函数

glob.iglob()函数获取一个可遍历对象,使用它可以逐个获取匹配的文件路径名。与glob.glob()的区别是:glob.glob()同时获取所有的匹配路径,而glob.iglob()一次只获取一个匹配路径;

"""
三、文件通配符
Python的glob模块可以实现查找符合特定规则的文件路径名功能
查找文件一般用到如下三个匹配符:”” 、“?” 、“[]”
”” 匹配0个或多个字符;
”?” 匹配单个字符;
”[]” 匹配指定范围内的字符;如[0-9]匹配数字
"""

import glob
import os

# glob.glob()函数一次性获取相对路径下指定格式的所有文件
Relative_path = r"./*.py"
print("glob.glob()函数一次性获取相对路径下指定格式的所有文件:")
for i in glob.glob(Relative_path):
    print(i)
print("glob.glob(Relative_path)返回值类型:" , type(glob.glob(Relative_path)))

# glob.glob()函数一次性获取绝对路径下指定格式的所有文件
Absolute_path = os.getcwd() + "/*.py"
print("glob.glob()函数一次性获取绝对路径下指定格式的所有文件:")
for i in glob.glob(Absolute_path):
    print(i)

# glob.iglob()函数一次获取相对路径下指定格式的一个文件
Relative_path = r"./*.py"
print("glob.iglob()函数一次获取相对路径下指定格式的一个文件:")
for i in glob.iglob(Relative_path):
    print(i)
print("glob.iglob(Relative_path)返回值类型:" , type(glob.iglob(Relative_path)))
glob.glob()函数一次性获取相对路径下指定格式的所有文件:
./1.py
./ZX_01_操作系统.py
./__init__.py
./ZX_02_文件通配符glob函数.py
glob.glob(Relative_path)返回值类型: <class 'list'>
glob.glob()函数一次性获取绝对路径下指定格式的所有文件:
/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/1.py
/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/ZX_01_操作系统.py
/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/__init__.py
/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/ZX_02_文件通配符glob函数.py
glob.iglob()函数一次获取相对路径下指定格式的一个文件:
./1.py
./ZX_01_操作系统.py
./__init__.py
./ZX_02_文件通配符glob函数.py
glob.iglob(Relative_path)返回值类型: <class 'generator'>

3.3、使用glob.glob()获得文件路径

a)、获得当前文件夹下的所有文件

path参数为相对路径“./*”或者“*”;

b)、获得当前目录的某个子目录的文件A

子文件也属于相对路径,所以使用“./*/filenameA”或者“*/filenameA”。这里的“*/”代表下一层文件夹;

c)、当前处于目录A,获取目录B下文件C的路径

建议使用绝对路径,也就是使用类似“/*/*”的参数;

# “./*”或者“*”获得当前文件夹下的所有文件
print("(“./*”)或者(“*”)获得当前文件夹下的所有文件:"
      , glob.glob("./*"))

# (“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件
print("(“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件:"
      , glob.glob("./file/*"))

print("(“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件:"
      , glob.glob("./*/file1.py"))

print("(“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件:"
      , glob.glob("*/file2.py"))

# 当前处于目录A(ZX_22_标准库),获取目录B(ZX_21_命名空间和作用域)下文件C(file_dir(os))的路径
print(os.getcwd())
print(glob.glob("../*/file_dir(os)"))
(“./*”)或者(“*”)获得当前文件夹下的所有文件: ['./1.py', './ZX_01_操作系统.py', './file', './__init__.py', './ZX_02_文件通配符glob函数.py']
(“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件: ['./file/file2.py', './file/file1.py']
(“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件: ['./file/file1.py']
(“./*/filename”)或者(“*/filename”)获得当前目录的某个子目录的文件: ['file/file2.py']
/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库
['../ZX_21_命名空间和作用域/file_dir(os)']

四、命令行参数

sys.argv[]是一个从程序外部获取参数的桥梁,因我们从外部获取的参数可以是多个,所以sys.argv返回一个列表(list),所以才能用[]提取其中的元素,其中sys.argv[0]第一个元素是程序本身,即程序的路径,随后依次是外部给予的参数;

test.py代码如下:

# 四、命令行参数
# sys.argv[0]返回本文件路径
print("sys.argv[0]返回本文件路径:" , sys.argv[0])
# sys.argv返回列表list
print("sys.argv返回列表list:" , sys.argv)
# 从第二个元素开始输出
print("sys.argv[1:]:" , sys.argv[1:])

交互器中运行如下脚本,增加参数"this is a python"

输出结果如下:

zx@zx:~$ python3 '/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/1.py' this is a python
sys.argv[0]返回本文件路径: /home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/1.py
sys.argv返回列表list: ['/home/zx/ZX/MyProject/Python/Runoob/ZX_22_标准库/1.py', 'this', 'is', 'a', 'python']
sys.argv[1:]: ['this', 'is', 'a', 'python']

综上可看出,Sys.argv[ ]其实就是一个列表,里边的数据项就是用户输入的参数,参数是从程序外部输入的,而非代码本身,要想看到它的效果可以将程序保存,从外部运行程序并给出参数

五、错误输出重定向和程序终止

几种常见重定向的方式,参考文档:https://www.jb51.net/article/90506.htm

大多脚本的定向终止都使用 "sys.exit()"

5.1、控制台重定向

最简单常用的输出重定向方式是利用控制台命令,这种重定向由控制台完成,与Python本身无关;

Windows命令提示符(cmd.exe)和Linux Shell(bash等)均通过">"或">>"将输出重定向。其中,">"表示覆盖内容,">>"表示追加内容。类似地,"2>"可重定向标准错误。重定向到"nul"(Windows)或"/dev/null"(Linux)会抑制输出,既不屏显也不存盘;

以Windows命令提示符为例,将Python脚本输出重定向到文件:

E:\>echo print 'hello' > test.py    #  print 'hello' 代码块重定向写入test.py中
E:\>test.py > out.txt    #  test.py文件重定向至out.txt,覆盖内容
E:\>type out.txt    #  type命令直接显示文本文件内容,类似Linux系统的cat命令
hello
E:\>test.py >> out.txt    #  test.py文件重定向至out.txt,追加内容
E:\>type out.txt
hello
hello
E:\>test.py > nul    #  重定向到"nul"(Windows)会抑制输出,既不屏显也不存盘

Linux Shell中执行Python脚本时,命令行应以"python"开头。除">"或">>"重定向外,还可使用tee命令。该命令可将内容同时输出到终端屏幕和(多个)文件中,"-a"选项表示追加写入,否则覆盖写入;

zx@zx:~$ python3 -c "print ('hello python')"
hello python
zx@zx:~$ python3 -c "print ('hello python')" > out.txt
zx@zx:~$ cat out.txt
hello python
zx@zx:~$ python3 -c "print ('hello python')" >> out.txt
zx@zx:~$ cat out.txt
hello python
hello python
zx@zx:~$ python3 -c "print ('I am')" | tee out.txt
I am
zx@zx:~$ python3 -c "print ('白杨')" | tee -a out.txt
白杨
zx@zx:~$ cat out.txt
I am
白杨
zx@zx:~$ python3 -c "print ('hello python')" > /dev/null

5.2、print 函数重定向

python2.x:

print  >> filename , expr

此方式基于print语句的扩展形式,即"print obj >> expr"(输出的obj对象追加重定向至expr中);

其中obj为一个file-like(尤其是提供write方法的)对象,为None时对应标准输出(sys.stdout);expr将被输出到该文件对象中;

python3.x:

print( expr , file = filename )

# print 函数重定向
from io import StringIO
import sys

memo=StringIO()
serr=sys.stderr
file=open('out.txt','w+')

print('StringIO' , memo)
print('stderr' , serr)
print('file' , file)
print(memo.getvalue() , None)
StringIO <_io.StringIO object at 0x7f08dba15168>
stderr <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>
file <_io.TextIOWrapper name='out.txt' mode='w+' encoding='UTF-8'>
 None

5.3、sys.stdout重定向

将一个可写对象(如file-like对象)赋给sys.stdout,可使随后的print语句输出内容重定向至该对象。重定向结束后,将sys.stdout恢复最初的缺省值,即标准输出。

import sys
# 5.3、sys.stdout重定向
# 方法一:
# 保存标准输出流
savedStdout = sys.stdout
# 打开文件,用于保存标准输出流内容
with open('./out.txt', 'w+') as file:
    # 标准输出重定向至文件,以下print输出的内容均被重定向至文件file内
    sys.stdout = file
    print('方法:This message is for file!')
    print('方法:print输出的内容被重定向至文件file内')
# 恢复标准输出流
sys.stdout = savedStdout
print('方法:This message is for screen!')
print('方法:print输出的内容显示在屏幕上')
方法:This message is for screen!
方法:print输出的内容显示在屏幕上
import os, sys
from io import StringIO

# 自定义多种具有write()方法的file-like对象,满足不同重定向需求
class RedirectStdout:
    def __init__(self):
        self.content = ''
        self.savedStdout = sys.stdout
        self.memObj, self.fileObj, self.nulObj = None, None, None

    # 外部的print语句将执行本write()方法,并由当前sys.stdout输出
    def write(self, outStr):
        self.content.append(outStr)
        #self.content += outStr

    # 标准输出重定向至控制台
    def toCons(self):
        # sys.__stdout__
        sys.stdout = self.savedStdout

    # 标准输出重定向至内存
    def toMemo(self):
        self.memObj = StringIO()
        sys.stdout = self.memObj

    # 标准输出重定向至文件
    def toFile(self, file='./out.txt'):
        self.fileObj = open(file, 'a+', 1)  # 改为行缓冲
        sys.stdout = self.fileObj

    # 抑制输出
    def toMute(self):
        self.nulObj = open(os.devnull, 'w')
        sys.stdout = self.nulObj

    def restore(self):
        self.content = ''
        if self.memObj.closed != True:
            self.memObj.close()
        if self.fileObj.closed != True:
            self.fileObj.close()
        if self.nulObj.closed != True:
            self.nulObj.close()
        sys.stdout = self.savedStdout  # sys.__stdout__

# 实例化
redirObj = RedirectStdout()
#本句会抑制"Let's begin!"输出
sys.stdout = redirObj
print("Let's begin!")
# 屏显'Hello World!'和'I am Gavin.'(两行)
print('Hello World!' , redirObj.toCons())
print('I am Gavin' , redirObj.toCons())
# 写入'How are you?'和"Can't complain."(两行)
print('How are you?' , redirObj.toFile())
print("Can't complain." , redirObj.toFile())
# 屏显
print("What'up?" , redirObj.toCons())
# 无屏显或写入
print('<Silence>' , redirObj.toMute())
# 控制台屏显'Never redirect me!'
os.system('echo Never redirect me!')
# 无屏显或写入
print('What a pity!' , redirObj.toMemo())
# 屏显
print('Hello?' , redirObj.toCons())
# 该串写入文件
print("Oh, Gavin can't hear me" , redirObj.toFile())
redirObj.restore()
# 屏显
print('Pop up')
Hello World! None
I am Gavin None
What'up? None
Never redirect me!
Hello? None
Pop up

out.txt文件内容:

How are you? None
Can't complain. None
Oh, Gavin can't hear me None

5.4、上下文管理器(Context Manager)

借助于上下文管理器语法,可不必向重定向使用者暴露sys.stdout

首先考虑输出抑制,基于上下文管理器语法实现如下:

import sys , contextlib
from io import StringIO

class DummyFile:
  def write(self, outStr): pass

@contextlib.contextmanager
def MuteStdout():
  savedStdout = sys.stdout
  sys.stdout = StringIO() #DummyFile()
  try:
    yield
  except Exception: #捕获到错误时,屏显被抑制的输出(该处理并非必需)
    content, sys.stdout = sys.stdout, savedStdout
    print (content.getvalue()) #; raise
  #finally:
  sys.stdout = savedStdout

使用示例如下:

with MuteStdout():
  print "I'll show up when <raise> is executed!" #不屏显不写入
  raise #屏显上句
  print "I'm hiding myself somewhere:)" #不屏显

再考虑更通用的输出重定向:

import os, sys
from contextlib import contextmanager
@contextmanager
def RedirectStdout(newStdout):
  savedStdout, sys.stdout = sys.stdout, newStdout
  try:
    yield
  finally:
    sys.stdout = savedStdout

使用示例如下:

def Greeting(): print 'Hello, boss!'

with open('out.txt', "w+") as file:
  print "I'm writing to you..."  #屏显
  with RedirectStdout(file):
    print 'I hope this letter finds you well!' #写入文件
  print 'Check your mailbox.'   #屏显

with open(os.devnull, "w+") as file, RedirectStdout(file):
  Greeting()           #不屏显不写入
  print 'I deserve a pay raise:)' #不屏显不写入
print 'Did you hear what I said?'  #屏显

可见,with内嵌块里的函数和print语句输出均被重定向。注意,上述示例不是线程安全的,主要适用于单线程。

当函数被频繁调用时,建议使用装饰器包装该函数。这样,仅需修改该函数定义,而无需在每次调用该函数时使用with语句包裹。示例如下:

import sys, cStringIO, functools
def MuteStdout(retCache=False):
  def decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
      savedStdout = sys.stdout
      sys.stdout = cStringIO.StringIO()
      try:
        ret = func(*args, **kwargs)
        if retCache == True:
          ret = sys.stdout.getvalue().strip()
      finally:
        sys.stdout = savedStdout
      return ret
    return wrapper
  return decorator

若装饰器MuteStdout的参数retCache为真,外部调用func()函数时将返回该函数内部print输出的内容(可供屏显);若retCache为假,外部调用func()函数时将返回该函数的返回值(抑制输出)。

MuteStdout装饰器使用示例如下:

@MuteStdout(True)
def Exclaim(): print 'I am proud of myself!'

@MuteStdout()
def Mumble(): print 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值