文件操作

文件操作

文件操作

冯诺依曼体系架构

    CPU由控制器和运算器组成.

    运算器: 完成各种算数运算,逻辑运算,数据传输等数据加工处理;

    控制器: 控制程序的执行;

    存储器: 用于记忆程序和数据,例如内存等;

    输入设备: 将数据或者程序输入到计算机中,例如键盘,鼠标等;

    输出设备: 将数据或程序的处理结果展示给用户,例如显示器,打印机等.

    一般的IO操作, 指文件IO, 如果指的是网络IO,都会直接说网络IO.

文件操作

    文件IO常用操作:

    open, read, write, close

    readline: 行读取;

    readlines: 多行读取;

    seek: 文件指针操作;

    tell: 指针位置.

打开操作:

    open(file, mode='r', buffering=-1, encoding=None, newline=None, closefd=True, opener=None)

打开一个文件,返回一个文件对象(流对象)和文件描述符,打开文件失败,则返回异常.

文件操作中, 最常用的操作就是读和写.

文件访问的模式有两种: 文本模式和和二进制模式, 不同模式,操作函数不同,表现结果也不一样.

open操作的参数:

    file: 打开或者要创建的文件名, 如果不指定路径,默认是当前路径.

    mode模式:

r: 缺省,表示只读打开, 文件不存在或使用write方法, 会抛异常.

w: 只写打开,读取则抛异常,文件不存在则创建,反之清空文件内容.

x: 创建并写入一个新文件,只读方式打开, 文件存在则抛异常.

a: 写入打开,文件存在则追加;

b: 二进制模式; 将文件按字节理解,与字符编码无关,二进制模式操作时,字节操作使用bytes类型.

t: 缺省的,文本模式,字符流,将文件字节按某种字符编码理解,按字符操作,open的默认mode是rt.

+: 读写打开一个文件, 给原来只读,只写文件打开提供缺失的读或写的功能,不能单独使用.    

rb 二进制文件

w或wt 文本模式写,打开前文件存储被清空;

wb 二进制写,文件存储同样被清空;

a+ 可读写模式,写只能写在文件末尾;

w+ 可读写,与a+的区别是要清空文件内容;

r+ 可读写,与a+的区别是可以写到文件任何位置;

   

文件指针:

    mode=r, 指针起始在0;

    mode=a, 指针起始在EOF;

    tell(), 显示指针当前位置.

   

    seek(offset[, whence])

    移动文件指针位置. offset偏移多少字节, whence从哪里开始.

    文本模式下:

    whence 0 缺省值,表示从头开始, offset只能是正整数.

    whence 1 表示从当前位置, offset只接受0.

    whence 2 表示从EOF开始,offset只接受0.

   

    二进制模式下:

    whence 0 缺省值, 表示从头开始, offset只能是正整数.

    whence 1 表示从当前位置, offset可正可负.

    whence 2 表示从EOF开始, offset可正可负.

二进制模式支持任意起点的偏移,从头,从尾,从中间位置开始.

向后seek可以超界,但是向前seek的时候,不能超界,否则抛异常.

bufferint: 缓冲区

    -1表示使用缺省大小的buffer.如果是二进制模式,使用io.DEFAULT_BUFFER_SIZE值,默认是4096或者8192.如果是文本模式/终端设备,是行缓存方式,反之则使用二进制模式策略.

    0只在二进制模式使用,表示关buffer.

    1只在文本模式使用,表示使用行缓冲,意思是见到换行符就flush.

    大于1用于指定buffer的大小.

   

    buffer缓存区:

       缓冲区一个内存空间,一般来说是一个FIFO队列,到缓冲区满了或达到阈值,数据才会flush到磁盘.

       flush()将缓冲区数据写入磁盘.

       close()关闭前会调用flush().

       io.DEFAULT_BUFFER_SIZE缺省缓冲区大小,字节.

  

    总结:

       1, 文本模式,一般都用默认缓冲区大小;

       2, 二进制模式,是一个个字节的操作,可以指定buffer的大小;

       3, 一般,默认缓冲区大小是个比较好的选择,除非明确知道,否则不调用它;

       4, 一般编程中,明确知道需要写磁盘了,都会手动调用一次flush,而不是等到自动flush或者close的时候.

   

encoding:编码, 仅文本模式使用.

encoding表示的是返回的数据采用何种编码,一般采用utf8或者gbk;

Nome表示使用缺省编码,依赖操作系统.

其他参数:

errors: 什么样的编码错误将被捕获.

None和strict表示有编码错误将抛出ValueError异常; ignore表示忽略.

newline: 文本模式中,换行的转换. 可以为None, '', ' ', ' ', ' '.

    读时, None表示' ', ' ', ' '都会被转换成' '; ''表示不会自动转换通用换行符;其他合法字符表示换行符就是指定字符,就会按照指定字符分行.

    写时, None表示' '都会被替换为系统缺省分隔符os.sleep; ' '或表示' '不替换; 其他合法字符表示' '会被替换为指定的字符.

closefd: 关闭文件描述符,True表示关闭它, False会在文件关闭后保持这个描述符.

fileobj.fileno() 查看.

read:

    read(size = -1)

       size表示读取的多少个字符或字节; 负数或者None表示读取到EOF.

行读取:

    readline(size = -1)

       一行行读取文件内容. size设置一次能读取行内几个字符或字节;

    readlines(hint = -1)

       读取所有行的列表, 指定hint则返回指定的行数.

    write:

       write(s), 把字符串s写入到文件中并返回字符的个数;

   

    flush:

       将文件写入到硬盘.

   

    close:

       flush并关闭文件对象;

       文件已经关闭, 再次关闭没有任何效果.

   

    其他:

       seekable(), 是否可seek.

       readable(), 是否可读写.

       writeable(), 是否可写.

       closed(), 是否已经关闭.

   

    上下文管理:

    问题:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

# Linux下执行:

(env353) [ames@ames python3.5.3]$ ipython3

Python 3.5.3 (default, Sep 11 2017, 14:06:47)

Type 'copyright', 'credits' or 'license' for more information

IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.

 

In [1]: lst = []

 

In [2]: for _ in range(100000):

   ...:     lst.append(open('test'))

   ...:    

---------------------------------------------------------------------------

OSError                                   Traceback (most recent call last)

<ipython-input-2-dbd507030346> in <module>()

      1 for _ in range(100000):

----> 2     lst.append(open('test'))

      3

 

OSError: [Errno 24] Too many open files: 'test'

 

In [3]:

   

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

 

(env353) [ames@ames python3.5.3]$ lsof -p 1399 | grep test | wc -l

0

(env353) [ames@ames python3.5.3]$ ulimit -a

core file size          (blocks, -c) 0

data seg size           (kbytes, -d) unlimited

scheduling priority             (-e) 0

file size               (blocks, -f) unlimited

pending signals                 (-i) 7283

max locked memory       (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited

open files                      (-n) 65535

pipe size            (512 bytes, -p) 8

POSIX message queues     (bytes, -q) 819200

real-time priority              (-r) 0

stack size              (kbytes, -s) 8192

cpu time               (seconds, -t) unlimited

max user processes              (-u) 7283

virtual memory          (kbytes, -v) unlimited

file locks                      (-x) unlimited

(env353) [ames@ames python3.5.3]$

 解决办法:

    1, 异常处理:

       当出现异常时,拦截异常,但是因为很多代码都可能出现OSError异常,不好判断异常就是因为资源限制产生的.

       使用finally可以保证打开的文件可以被关闭.

1

2

3

4

5

f = open('test'):

try:

    f.write('abc')  # 文件只读,写入失败.

finally:

    f.close()  # 这样才行.

   

    2, 上下文管理:

       一种特殊的语法,交给解释器去释放文件对象.

     上下文管理:

       1, 使用with ... as关键字.

       2, 上下文管理的语句并不会开启新的作用域.

       3, with语句执行完时,会自动关闭文件对象.

      另一种写法:

1

2

3

4

5

6

f1 = open('test')

with f1:

    f1.write('abc')  # 文件只读, 写入失败.

 

# 测试f是否关闭.

f1.closed  # f1的作用域.

对于类似于文件对象的IO对象,一般来说都需要在不使用时关闭,注销,以释放资源. IO被打开时,会获得一个文件描述符. 计算机资源有限,所以操作系统都会做限制.

就是为了保护计算机的资源不要被完全耗尽,计算资源是共享的,非独占. 一般情况下,除非特别明确知道资源情况,否则不要提高资源的限制值来解决此类问题

StringIO和BytesIO

    StringIO:  

          IO模块中的类: from io import StringIO

          内存中,开辟一个文本模式的buffer,可以像文件对象一样操作它.

          当close方法被调用时,这个buffer会被释放.

    StringIO操作:

          getvalue()获取全部内容,跟文件指针没有关系.

      

1

2

3

4

5

6

7

8

from io import StringIO

# 内存中构建.

sio = StringIO()  # 像文件对象一样操作.

print(sio.readable(), sio.writable(), sio.seekable())

sio.seek(0)

print(sio.readline())

print(sio.getvalue())  # 无视指针,输出全部内容.

sio.close()

    StringIO好处:     

       一般来说,磁盘操作比内存操作要慢很多,内存足够情况下,一般的优化思路是少落地,减少磁盘IO的过程,可以大大提高程序的运行效率.

    BytesIO:

       io模块中的类: from io import BytesIO

       内存中,开辟一个二进制模式的buffer,可以像文件对象一样操作它.

       当close方法被调用时,这个buffer会被释放.

   bytesIO操作:

1

2

3

4

5

6

7

8

from io import BytesIO  # 内存中构建.

 

bio = BytesIO()

print(bio.readable(), bio.writable(), bio.seekable())

bio.seek(0)

print(bio.readline())

print(bio.getvalue())  # 无视指针,输出全部内容.

bio.close()

    file-like对象:

       类文件对象, 可以像文件对象一样操作;

       socket对象, 输入输出对象(stdin, stdout)都是类文件对象.

   

1

2

3

4

from sys import stdout

f = stdout

print(type(f))

f.write('python')

路径操作          

    3.4版本开始, 建议使用pathlib模块, 提供Path对象来操作, 包括目录和文件.

    pathlib模块: from pathlib import Path

   目录操作:

   初始化:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

In [2]: from pathlib import Path

 

In [3]: p = Path()  # 等同于 p = Path('.')

 

In [4]: p

Out[4]: PosixPath('.')

 

In [5]: p = Path('a', 'b', 'c/d')

 

In [6]: p

Out[6]: PosixPath('a/b/c/d')

 

In [7]: p = Path('/etc')

 

In [8]: p

Out[8]: PosixPath('/etc')

 

In [9]:

    路径拼接和分解:  

    操作符: '/'

        Path对象/Path对象.

        Path对象/字符串 或者 字符串/Path对象.

    分解:

       parts属性,可以返回路径中的每一个部分;

    joinpath: 

    joinpath(*other) 连接多个字符串到Path对象中;

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

In [9]: p = Path()

 

In [10]: p = p / 'a'

 

In [11]: p

Out[11]: PosixPath('a')

 

In [12]: p1 = 'b' / p

 

In [13]: p1

Out[13]: PosixPath('b/a')

 

In [14]: p2 = Path('c')

 

In [15]: p2

Out[15]: PosixPath('c')

 

In [16]: p3 = p2 / p1

 

In [17]: p3

Out[17]: PosixPath('c/b/a')

 

In [18]: p3.parts

Out[18]: ('c', 'b', 'a')

 

In [19]: p3.joinpath('etc', 'init.d', Path('httpd'))

Out[19]: PosixPath('c/b/a/etc/init.d/httpd')

 

In [20]:

    获取路径:

       str获取路径字符串.

       bytes获取路径字符串的bytes.

1

2

3

4

5

6

In [20]: p = Path('/etc')

 

In [21]: str(p), bytes(p)

Out[21]: ('/etc', b'/etc')

 

In [22]:

   

    父目录:

       parent目录的逻辑父目录;

       parents父目录序列.

1

2

3

4

5

6

7

8

9

In [22]: p = Path('/a/b/c/d')

 

In [23]: p.parent.parent

Out[23]: PosixPath('/a/b')

 

In [24]: [x for x in p.parents]

Out[24]: [PosixPath('/a/b/c'), PosixPath('/a/b'), PosixPath('/a'), PosixPath('/')]

 

In [25]:

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

In [25]: p = Path('/etc/mysqlinstall/mysql.tar.gz')

 

In [26]: p.name

Out[26]: 'mysql.tar.gz'

 

In [27]: p.suffix

Out[27]: '.gz'

 

In [28]: p.suffixes

Out[28]: ['.tar', '.gz']

 

In [29]: p.stem

Out[29]: 'mysql.tar'

 

In [30]: p.with_name('mysql-5.tar')

Out[30]: PosixPath('/etc/mysqlinstall/mysql-5.tar')

 

In [31]: p = Path('README')

 

In [32]: p.with_suffix('.txt')

Out[32]: PosixPath('README.txt')

 

In [33]:

name, stem, suffix, suffixes, with_suffix(suffix), with_name(name)

 

name目录的最后一个部分.

 

suffix目录中最后一个部分的扩展名;

 

stem目录最后一个部分,没有后缀;

 

suffixes返回多个扩展名列表;

 

with_suffix(suffix)补充扩展名到路径尾部,返回新的路径,扩展名存在则无效;

 

with_name(name)替换目录最后一个部分并返回一个新的路径;

    cwd()返回当前工作目录;

    home()返回当前家目录;

   

    is_dir()  是否是目录;

    is_file() 是否是普通文件;

    is_symlink() 是否是软链接;

    is_socket()  是否是socket文件;

    is_block_device()  是否是块设备;

    is_char_device()  是否是字符设备;

    is_absolute()  是否是绝对路径;

   

    resolve()  返回一个新的路径, 这个新路径就是当前Path对象的绝对路径,如果是软链接则直接被解析;

    absolute()  也可以获取绝对路径,但是推荐使用resolve().

   

    exists()  目录或文件是否存在.

    rmdir()  删除空目录, 没有提供判断目录为空的方法;

    touch(mode=0o666, exist_ok=True)  创建一个文件;

    as_uri()  将路径返回成URI, 例如'file:///etc/passwd'.

   

mkdir(mode=0o777, parents=False, exist_ok=False)

parents, 是否创建父目录, True等同于mkdir -p; False时, 父目录不存在,则抛出FileNotFoundError.

 exist_ok参数,在3.5版本加入; False时,路径存在,抛出FileExistsError; True时,FileExistsError被忽略.

iterdit()  迭代当前目录;

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

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

In [34]: p = Path()

 

In [35]: p

Out[35]: PosixPath('.')

 

In [36]: p /= 'a/b/c/d'   # p = p / 'a/b/c/d'

 

In [37]: p

Out[37]: PosixPath('a/b/c/d')

 

In [38]: p.exists()

Out[38]: False

 

In [39]:

 

In [39]: p.mkdir()

---------------------------------------------------------------------------

FileNotFoundError                         Traceback (most recent call last)

<ipython-input-39-4c751e65273b> in <module>()

----> 1 p.mkdir()

 

~/.pyenv/versions/3.5.3/lib/python3.5/pathlib.py in mkdir(self, mode, parents, exist_ok)

   1212         if not parents:

   1213             try:

-> 1214                 self._accessor.mkdir(self, mode)

   1215             except FileExistsError:

   1216                 if not exist_ok or not self.is_dir():

 

~/.pyenv/versions/3.5.3/lib/python3.5/pathlib.py in wrapped(pathobj, *args)

    369         @functools.wraps(strfunc)

    370         def wrapped(pathobj, *args):

--> 371             return strfunc(str(pathobj), *args)

    372         return staticmethod(wrapped)

    373

 

FileNotFoundError: [Errno 2] No such file or directory: 'a/b/c/d'

 

In [40]: p.mkdir(parents=True)

 

In [41]: p.exists()

Out[41]: True

 

In [42]: p.mkdir(parents=True)

---------------------------------------------------------------------------

FileExistsError                           Traceback (most recent call last)

<ipython-input-42-09435c472033> in <module>()

----> 1 p.mkdir(parents=True)

 

~/.pyenv/versions/3.5.3/lib/python3.5/pathlib.py in mkdir(self, mode, parents, exist_ok)

   1218         else:

   1219             try:

-> 1220                 self._accessor.mkdir(self, mode)

   1221             except FileExistsError:

   1222                 if not exist_ok or not self.is_dir():

 

~/.pyenv/versions/3.5.3/lib/python3.5/pathlib.py in wrapped(pathobj, *args)

    369         @functools.wraps(strfunc)

    370         def wrapped(pathobj, *args):

--> 371             return strfunc(str(pathobj), *args)

    372         return staticmethod(wrapped)

    373

 

FileExistsError: [Errno 17] File exists: 'a/b/c/d'

 

In [43]: p.mkdir(parents=True, exist_ok=True)

 

In [44]: p /= 'readme.txt'

 

In [45]: p

Out[45]: PosixPath('a/b/c/d/readme.txt')

 

In [46]: p.parent.rmdir()

 

In [47]: p.parent.exists()

Out[47]: False

 

In [48]: p.mkdir()

---------------------------------------------------------------------------

FileNotFoundError                         Traceback (most recent call last)

<ipython-input-48-9edfab0e3b54> in <module>()

----> 1 p.mkdir()

 

~/.pyenv/versions/3.5.3/lib/python3.5/pathlib.py in mkdir(self, mode, parents, exist_ok)

   1212         if not parents:

   1213             try:

-> 1214                 self._accessor.mkdir(self, mode)

   1215             except FileExistsError:

   1216                 if not exist_ok or not self.is_dir():

 

~/.pyenv/versions/3.5.3/lib/python3.5/pathlib.py in wrapped(pathobj, *args)

    369         @functools.wraps(strfunc)

    370         def wrapped(pathobj, *args):

--> 371             return strfunc(str(pathobj), *args)

    372         return staticmethod(wrapped)

    373

 

FileNotFoundError: [Errno 2] No such file or directory: 'a/b/c/d/readme.txt'

 

In [49]: p.mkdir(parents=True)

 

In [50]: p

Out[50]: PosixPath('a/b/c/d/readme.txt')

 

In [51]:

     遍历, 并判断文件类型,如果为目录,是否可以判断其是否为空:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

 

from pathlib import Path

 

p = Path()

p /= 'a/b/c/d'

 

for x in p.parents[len(p.parents)-1].iterdir():

    print(x, end=' ')

    if x.is_dir():

        flag = False

        for _ in x.iterdir():

            flag = True

            break

        # for是否可以使用else子句?

        print('dir', 'Not Empty' if flag else 'Empty', sep=' ')

    elif x.is_file():

        print('file')

    else:

        print('other file')

通配符:

    glob(pattern) 通配给定的模式;

    rglob(pattern) 通配给定的模式,递归目录;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

In [4]: from pathlib import Path

 

In [5]: p = Path()

 

In [6]: list(p.glob('test*'))   # 返回当前目录对象下的test开头的文件;

Out[6]: [PosixPath('test')]

 

In [7]: list(p.glob('**/*.py'))   # 递归所有目录,等同于rglob.

Out[7]: []

 

In [8]: list(p.rglob('*.py'))

Out[8]: []

 

In [9]:

        匹配:

       match(pattern)

       模式匹配,成功返回True.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

In [1]: from pathlib import Path

 

In [2]: Path('/a/b/c.py').match('b/*.py')

Out[2]: True

 

In [3]: Path('/a/b.py').match('*.py')

Out[3]: True

 

In [4]: Path('/a/b/c.py').match('a/*.py')

Out[4]: False

 

In [5]: Path('/a/b/c.py').match('a/*/*.py')

Out[5]: True

 

In [6]: Path('/a/b/c.py').match('a/**/*.py')

Out[6]: True

 

In [7]: Path('/a/b/c.py').match('**/*.py')

Out[7]: True

 

In [8]:

    文件操作:

       open(mode='r', buffering=-1, ending=None, errors=None, newline=None)

       使用方法类似内建函数open. 返回一个文件对象.

    py3.5增加的新函数:

       read_bytes()

           以'rb'读取路径对应文件,并返回二进制流. 具体看源码.

          

       read_text(encoding=None, errors=None)

           以'rt'方式读取路径对应文件,返回文本.

      

       Path.write_bytes(data)

           以'wb'方式写入数据到路径对应文件.

   

       write_text(data, encoding=None, errors=None)

           以'wt'方式写入字符串到路径对应文件.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

 

from pathlib import Path

 

p = Path('my_binary_file')

p.write_bytes(b'Binary file contents')

p.read_bytes()  # b'Binary file contents'

 

p = Path('my_text_file')

p.write_text('Text file contents')

p.read_text()  # 'Text file contents'

 

p = Path(r'C:Users31948Desktop est.py')

p.write_text('hello python')

print(p.read_text)

with p.open() as f:

    print(f.read(5))

shutil, csv, ini

    os.name -> windows是nt, linux是posix.

    os.uname() -> Linux支持显示.

    sys.platform  -> windows显示win32, linux显示linux.

   

    os.listdir('o:/temp')  -> 返回目录内容文件.

   

    os也有open, read, write等方法, 但太低级,建议使用内建函数open, read, write.

    os.stat(path, *, dir_fd=None, follow_symlinks=True)

       调用linux系统的stat.

       path: 路径的string或者bytes, 后者fd.

       follow_symlinks True 返回文件本身信息, False且如果是软链接则显示软链接本身.

    os.chown(path, uid, gid)  -> 改变文件的属主,属组,但需要足够的权限.

 shutil模块

       目前为止,文件的拷贝,使用打开2个文件对象,源文件读取内容,写入目标文件中来完成拷贝过程,但这样会丢失stat数据信息(权限等),因为根本就没复制过去.

       python提供了一个方便的库shutil(高级文件操作).

copy复制:

    copyfileobj(fsrc, fdst[, length])

    文件对象的复制,fsrc和fdst是open打开的文件对象,复制内容,fdst要求可写.

    length指定了表示buffer的大小;

1

2

3

4

5

6

7

8

import shutil

 

with open(r'C:Users31948Desktop estone.txt', 'r+') as f1:

    f1.write('abcd 1234')

    f1.seek(0)

    f1.flush()

    with open(r'C:Users31948Desktop estfirst.txt', 'w+') as f2:

        shutil.copyfileobj(f1, f2)

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

    复制文件内容,不含元数据; src, dst为文件的路径字符串;

    本质上调用的就是coppyfileobj, 所以不带元数据二进制内容复制.

     copymode(src,dst,*,follow_symlinks=True)  -> 仅仅复制权限.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

# windows下,进入src和dst文件的父目录下:

In [1]: import shutil, os

 

In [2]: shutil.copymode('one.txt', 'first.txt')

 

In [3]: os.stat('one.txt')

Out[3]: os.stat_result(st_mode=33206, st_ino=23643898043816899, st_dev=3188908737, st_nlink=1, st_uid=0, st_gid=0, st_size=10, st_atime=1509104520, st_mtime=1509109637, st_ctime=1509104520)

 

In [4]: os.stat('first.txt')

Out[4]: os.stat_result(st_mode=33206, st_ino=37999121856060367, st_dev=3188908737, st_nlink=1, st_uid=0, st_gid=0, st_size=10, st_atime=1509104525, st_mtime=1509109637, st_ctime=1509104520)

 

In [5]:

    copystat(src, dst, *, follow_symlinks=True)  -> 复制元数据,stat包含权限.

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

33

34

35

36

37

38

39

40

41

42

43

44

45

46

# Linux下操作:

(env353) [python@ames test]$ stat ont.txt

stat: cannot stat ‘ont.txt’: No such file or directory

(env353) [python@ames test]$ ls

first.txt  one.txt  Untitled.ipynb

(env353) [python@ames test]$

(env353) [python@ames test]$ stat one.txt

  File: ‘one.txt’

  Size: 0         Blocks: 0          IO Block: 4096   regular empty file

Device: fd00h/64768d    Inode: 1087835     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1001/  python)   Gid: ( 1001/  python)

Context: unconfined_u:object_r:user_home_t:s0

Access: 2017-10-27 09:55:08.379019965 -0400

Modify: 2017-10-27 09:55:08.379019965 -0400

Change: 2017-10-27 09:55:08.379019965 -0400

 Birth: -

(env353) [python@ames test]$ stat first.txt

  File: ‘first.txt’

  Size: 0         Blocks: 0          IO Block: 4096   regular empty file

Device: fd00h/64768d    Inode: 1087717     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1001/  python)   Gid: ( 1001/  python)

Context: unconfined_u:object_r:user_home_t:s0

Access: 2017-10-27 09:56:08.836225291 -0400

Modify: 2017-10-27 09:56:08.836225291 -0400

Change: 2017-10-27 09:56:08.836225291 -0400

 Birth: -

(env353) [python@ames test]$

# 打开ipython

In [1]: import shutil

 

In [2]: shutil.copystat('first.txt', 'one.txt')

 

In [3]:

 

# 再次查看:

(env353) [python@ames test]$ stat one.txt

  File: ‘one.txt’

  Size: 0         Blocks: 0          IO Block: 4096   regular empty file

Device: fd00h/64768d    Inode: 1087835     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1001/  python)   Gid: ( 1001/  python)

Context: unconfined_u:object_r:user_home_t:s0

Access: 2017-10-27 09:56:08.836225291 -0400

Modify: 2017-10-27 09:56:08.836225291 -0400

Change: 2017-10-27 10:01:04.778385230 -0400

 Birth: -

(env353) [python@ames test]$

    copy(src, dst, *, follow_symlinks=True)  -> 复制文件内容,权限和部分元数据,不包括创建时间和修改时间;

    本质上调用的是:

       copyfile(src, dst, follow_symlinks=follow_symlinks)

       copymode(src, dst, follow_symlinks=follow_symlinks)

    copy2比copy多了复制全部元数据,但需要平台支持.

    本质上调用的是:

       copyfile(src, dst, follow_symlinks=follow_symlinks)

       copystat(src, dst, follow_symlinks=follow_symlinks)

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

       递归复制目录. 默认使用copy2, 也就是带更多的元数据复制.

    src, dst必须是目录, src必须存在, dst必须不存在.

    ignore=func, 提供一个callable(src, names)  -> ignore_names. 提供一个函数, 它会被调用. src是源目录, names是os.listdir(src)的结果, 就是列出src中的文件名, 返回值是要被过滤的文件名的set类型数据.

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

33

34

# Linux下操作:

(env353) [python@ames test]$ tree tmp

tmp

├── a

└── b

 

2 directories, 0 files

(env353) [python@ames test]$

(env353) [python@ames test]$ tree tt

tt [error opening dir]

 

0 directories, 0 files

(env353) [python@ames test]$

(env353) [python@ames test]$ ipython

Python 3.5.3 (default, Sep 12 2017, 03:35:37)

Type 'copyright', 'credits' or 'license' for more information

IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.

 

In [1]: import shutil

 

In [2]: def ignore(src, names):

   ...:     ig = filter(lambda x: x.startswith('a'), names)

   ...:     return set(ig) 

   ...:

 

In [3]:  shutil.copytree('tmp', 'tt/o', ignore=ignore)

Out[3]: 'tt/o'

(env353) [python@ames test]$ tree tt

tt

└── o

    └── b

 

2 directories, 0 files

(env353) [python@ames test]$

rm删除

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

    递归删除. 如同rm -rf一样危险,慎用.

    它不是原子操作,有可能删除错误,就会中断,已经删除的就删除了.

    ignore_errors为true,忽略错误. 当为False或omitted时, onerror生效.

    onerror为callable,接受函数function, path和execinfo.

1

Shutil.rmtree('o:/tmp')  # 类似 rm -rf操作.

move移动

    move(src, dst, copy_function=copy2)

    递归移动文件/目录到目标, 返回目标.

    本身使用的是os.rename方法.

    如果不支持rename,如果是目录则想copytree再删除源目录.

    默认使用copy2方法.

1

2

os.rename('o:/t.txt', 'o:/temp/t')

os.rename('test3', '/tmp/py/test300')

   

    shutil还支持打包功能,生成tar并压缩,支持zip,gz,bz,xz.

csv文件

    csv文件简介:

       逗号分隔符 Comma-Separated Values.

       CSV是一个被行分割符,列分割符划分成行和列的文本文件.

       没有指定的字符编码.

       参考: http://www.ietf.org/rfc/rfc4180.txt

       行分隔符为 ,最后一行可以没有换行符.

       列分隔符常为逗号或制表符.

       每一行成为一条记录record.

       字段可以使用双引号括起来,也可不使用.如果字段中出现双引号/逗号,换行符必须用双引号括起来,如果字段值是双引号,使用两个双引号表示一个转义.

       表头可选,和字段列对齐.

       手动生成csv文件:

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

33

34

In [5]: pwd

Out[5]: '/home/python/test'

 

In [6]: from pathlib import Path

 

In [7]: p = Path('/home/python/test/t.csv')

 

In [8]: parent = p.parent

 

In [9]: if not parent.exists():

   ...:     parent.mkdir(parents=True)

   ...:     

 

In [10]: csv_body = '''

    ...: id, name, age, comment

    ...: 1, zs, 18, "I'm 18"

    ...: 2, ls, 20, "this is a ""test"" string."

    ...: 3, www, 23, "中国

    ...: 国庆

    ...: "

    ...: '''

 

In [11]: p.write_text(csv_body)

Out[11]: 108

 

In [12]: cat t.csv

id, name, age, comment

1, zs, 18, "I'm 18"

2, ls, 20, "this is a ""test"" string."

3, www, 23, "中国

国庆

"

 

In [13]:

    csv模块:

       reader(csvfile, dialect='excel', **fmtparams)

       返回DictReader的实例,是个行迭代器.

       delimiter列分隔符,逗号.

       lineterminator行分隔符 .

       quuotechar字段的引用符号,缺省为双引号("").

       双引号的处理:

           doublequote双引号的处理,默认为True.如果和quotechar为同一个,True则使用2个双引号表示,False表示使用转义字符将作为双引号的前缀.

           escapechar一个转义字符,默认为None.

           quoting指定双引号的规则. QUOTE_ALL所有字段; QUOTE_MINIMAL特殊字符字段;

           QUOTE_NONNUMERIC非数字字段; QUOTE_NONE都不使用引号.

       writer(csvfile, dialect='excel', **fmtparams)

       返回DictWriter的实例.

        主要方法有writerow, writerows.

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

33

34

35

36

37

38

39

# linux下:

In [15]: import csv

 

In [16]: from pathlib import Path

 

In [17]: p = Path('t.csv')  

 

In [19]: row = [4, 'tom', 22, 'tom']

 

In [20]: rows = [(5, 'jerry', 24, 'jerry'), (6, 'justin', 22, 'just "int')]

 

In [21]: with open(str(p), 'a+') as f:

    ...:     writer = csv.writer(f)

    ...:     writer = writerow(row)

    ...:     writer.writerows(rows)

    ...:    

---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-21-2dde75aff59c> in <module>()

      1 with open(str(p)) as f:

      2     writer = csv.writer(f)

----> 3     writer = writerow(row)

      4     writer.writerows(rows)

      5

 

NameError: name 'writerow' is not defined

 

In [23]: with open(str(p), 'a+') as f:

    ...:     writer = csv.writer(f)

    ...:     # writer = writerow(row)

    ...:     writer.writerows(rows)

    ...:    

 

In [24]:

(env353) [python@ames test]$ cat t.csv

 

5,jerry,24,jerry

6,justin,22,"just   ""int"

(env353) [python@ames test]$

ini文件处理:

    作为配置文件,ini格式的文件很流行:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

[root@ames ~]# cat /etc/my.cnf

[client]

#password = your_password

port      = 3306

socket    = /tmp/mysql.sock

 

[mysqldump]

quick

max_allowed_packet = 16M

 

[mysql]

no-auto-rehash

 

[myisamchk]

key_buffer_size = 8M

sort_buffer_size = 8M

 

[mysqlhotcopy]

interactive-timeout

    中括号里面的部分称为section.

    每一个section内,都是key-value形成的键值对,key称为option选项. 

原文地址:https://www.cnblogs.com/amesy/p/7920308.html