主要是下面的内容:
-
文件对象:内建函数、内建方法、属性
-
标准文件
-
文件系统:访问方法、文件执行
-
持久化存储
-
标准库中与文件有关的模块
1.文件对象
文件对象是用来访问文件的接口,而文件只是连续的字节序列,数据的传输经常会用到字节流,无论字节流是由单个字节还是大块数据组成。
2.文件内建函数(open()和file())
内建函数open()以及file()提供了初始化输入/输出(I/O)操作的通用接口,如果打开文件成功,则会返回一个文件对象,否则会引发IOError异常,open()和file()并没有任何区别,可以任意替换,基本语法如下:
1
|
file_object
=
open
(file_name, access_mode
=
'r'
, buffering
=
-
1
)
|
说明如下:
-
file_name:包含要打开的文件名的字符串表示,可以是相对路径或绝对路径
-
access_mode:访问模式,可选参数,如果没有指定,默认值为'r'(字符串表示)
访问模式主要有下面几种:
模式 | 说明 |
'r' | 读取,文件必须要存在 |
'w' | 写入,文件存在则清空原来文件内容再写入;文件不存在则自动创建该文件并写入内容 |
'a' | 追加,文件存在只会在文件后面追加数据;文件不存在则自动创建该文件并写入内容 |
'+' | 表示可读可写,但不能单独使用,一般与'r'一起使用 |
'b' | 以二进制模式访问文件,但不能作为第一个字符出现,对于Unix系统来说,可能会被忽略掉,因为Unix系统默认把所有文件当作进制文件,所以使用'b'模式时,一般是希望在所有系统平台上都是用二进制模式来访问文件(比如在Windows上) |
'U' | 通用换行符支持(UNS),用来处理不同操作系统平台上的换行符(\n,\r或者\r\n),使用该模式时,文件对象的newlines属性会记录它曾“看到的”文件的行结束符,文件刚打开时,程序还没有遇到换行符,newlines值为None,在文件第一行被读取后,它被设置为第一行的结束符,如果遇到其他类型的行结束符,newlines会成为一个包含每种格式的元组。 不过需要注意的是,UNS中用于读取文本文件,没有对应的处理文件输出的方法。默认情况下该模式是打开的,如果不需要,可以在执行脚本文件时使用参数--without-universal-newlines |
常用的访问模式组合如下:
文件对象的访问模式 | |
文件模式 | 操作 |
r | 以读方式打开 |
rU或U | 以读方式打开,同时提供通用换行符支持 |
w | 以写方式打开(必要时清空) |
a | 以追加模式打开(从EOF开始,必要时创建新文件) |
r+ | 以读写模式打开 |
w+ | 以读写模式打开(参见w) |
a+ | 以读写模式打开(参见a) |
rb | 以二进制读模式打开 |
wb | 以二进制写模式打开(参见w) |
ab | 以二进制追加模式打开(参见a) |
rb+ | 以二进制读写模式打开(参见r+) |
wb+ | 以二进制读写模式打开(参见w+) |
ab+ | 以二进制读写模式打开(参见a+) |
-
buffering:用于指示访问文件所采用的缓冲方式,采用默认方式即可
0表示不缓冲,1表示缓冲一行数据,任何其他大于1的值代表使用给定值作为缓冲区大小。
3.文件内建方法
open()成功执行后会返回一个文件对象,对该文件的所有操作都通过这个句柄来完成,其操作方法如下:
(1)输入
主要如下:
-
read(size=-1):读取给定数目个字节并以字符串返回,size默认为-1或其他负值时,表示全部读取
1
2
3
4
5
6
7
8
9
10
|
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readlines()
[
'xpleafclyyh\n'
,
'cl\n'
]
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.read()
'xpleafclyyh\ncl\n'
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.read(
6
)
'xpleaf'
>>> f.close()
|
-
readline(size=-1):读取文件的一行并以字符串返回,size默认为-1或其他负值时,表示全部读取,给定size值时,如果小于当前行的字节数,则不完整地读取一行,否则则会完整读取该行
1
2
3
4
5
6
7
8
9
10
11
12
|
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readlines()
[
'xpleafclyyh\n'
,
'cl\n'
]
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readline()
'xpleafclyyh\n'
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readline(
6
)
'xpleaf'
>>> f.readline(
10
)
'clyyh\n'
>>> f.close()
|
-
readlines([size]):以列表的方式返回所有的行,不过在测试时size参数没有起作用
1
2
3
4
|
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readlines()
[
'xpleafclyyh\n'
,
'cl\n'
]
>>> f.close()
|
另外还有一个xreadlines()的方法,可以不用全部读取所有的行以节省空间,不过由于现在文件读取可以使用for循环迭代的方式,即for eachLine in file,所以可以不使用xreadlines()即可以节省内存空间。
在读取操作时可以看到,Pytthon不会自动为我们去掉换行符,所以一般我们这样处理:
1
2
3
|
f
=
open
(
'myFile'
,
'r'
)
data
=
[line.strip()
for
line
in
f.readlines()]
f.close()
|
同样,在下面的输出中,Python也不会自动为我们加上换行符,这个操作要我们自己完成。
(2)输出
主要如下:
-
write(str):把数据写入到文件中,需要写入一行数据时可以在字符串后面加行结束符即可,所以输出的方法并没有writeline()
1
2
3
4
5
6
7
8
9
|
>>> f
=
open
(
'test.txt'
,
'w'
)
>>> f.write(
'xpleaf'
)
>>> f.write(
'clyyh\n'
)
>>> f.write(
'cl\n'
)
>>> f.close()
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readlines()
[
'xpleafclyyh\n'
,
'cl\n'
]
>>> f.close()
|
-
writelines(seq):接受一个字符串列表作为参数,将它们写入文件,不过行结束符并不会被自动加上
1
2
3
4
5
6
7
8
|
>>> f
=
open
(
'test.txt'
,
'w'
)
>>> data
=
[
'xpleaf'
,
'test\n'
,
'clyyh\n'
]
>>> f.writelines(data)
>>> f.close()
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readlines()
[
'xpleaftest\n'
,
'clyyh\n'
]
>>> f.close()
|
(3)文件内移动
主要是下面的两个方法:
-
seek(offset[, whence]):移动文件指针到不同的位置,offset字节表示相对于位置whence的偏移量,whence的默认值为0,表示相对于文件的开头,1代表从当前位置算起,2代表从文件末尾算起
-
tell():返回当前文件指针所在的位置
举例如下:
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
|
>>> f
=
open
(
'test.txt'
,
'r'
)
>>> f.readlines()
[
'xpleafclyyh\n'
,
'cl\n'
]
>>> f.seek(
0
)
>>> f.read(
6
)
'xpleaf'
>>> f.tell()
6
>>> f.seek(
8
)
>>> f.tell()
8
>>> f.read()
'yyh\ncl\n'
>>> f.tell()
15
>>> f.seek(
-
3
,
1
)
>>> f.tell()
12
>>> f.read()
'cl\n'
>>> f.seek(
0
)
>>> f.tell()
0
>>> f.seek(
-
3
,
2
)
>>> f.tell()
12
>>> f.read()
'cl\n'
>>> f.close()
|
(4)文件迭代
在Python2.2之后,引进了迭代器和文件迭代,文件对象成为了它们自己的迭代器,因此可以通过使用for循环迭代(for line in file)的方式来取代xreadlines()的功能,这样的话就可以大大节省内存空间。因为文件对象本身就是一个迭代器,所以它有next()方法,并且在迭代完所有数据后会引发StopIteration异常。
(5)其他
其他内建方法如下:
-
close():通过关闭文件来结束对它的访问,如果不显式地关闭文件,那么可能丢失输出缓冲区的数据
-
flush():直接把内部缓冲区中的数据立刻写入文件
在执行f.write()的操作时,其实并没有把内容实时地写入到磁盘中,而是保存到内部缓冲区中,在文件关闭或执行flush()时都会保存在磁盘中。
-
flieno():返回打开文件的描述符
1
2
3
|
>>> f
=
open
(
'welcome.txt'
,
'r'
)
>>> f.fileno()
3
|
-
isatty():当文件是一个类tty设备时返回True,否则返回False
-
truncate([size]):将文件截取到当前文件指针位置或者到给定size,以字节为单位
所谓的截取其实就是把当前位置之后的文件内容删除,给定了size参数,表明从第几个字节开始截取(包括该字节),如果size没有给定,则默认从当前位置开始,如下:
1
2
3
4
5
6
7
8
9
10
11
|
>>> f
=
open
(
'test.txt'
,
'r+'
)
>>> f.read()
'clyyh'
>>> f.truncate()
>>> f.seek(
0
)
>>> f.read()
'clyyh'
>>> f.truncate(
2
)
>>> f.seek(
0
)
>>> f.read()
'cl'
|
(6)行分隔符与路径分隔符在不同操作系统中的差异
如下:
-
行分隔符:在POSIX(Unix系列或Mac OX X)系统上是'\n'字符,在旧的MacOS下是'\r',而DOS和Wind32系统下结合了两者'\r\n'
-
路径分隔符:POSIX使用'/',DOS和Windows使用'\',旧版本的MacOS使用':'
如果要创建跨平台的应用时,就需要处理这些差异,不过Python中的os模块已经有相关属性来为我们处理这些差异:
有助于跨平台开发的os模块属性 | |
os模块属性 | 描述 |
linesep | 用于在文件中分隔行的字符串 |
sep | 用来分隔文件路径名的字符串 |
pathsep | 用于分隔文件路径的字符串 |
curdir | 当前工作目录的字符串名称 |
pardir | (当前工作目录的)父目录字符串名称 |
下面是在Linux操作系统上的例子:
1
2
3
4
5
6
7
8
9
10
11
|
>>>
import
os
>>> os.linesep
'\n'
>>> os.sep
'/'
>>> os.pathsep
':'
>>> os.curdir
'.'
>>> os.pardir
'..'
|
下面是在Windows操作系统上的例子:
1
2
3
4
5
6
7
8
9
10
11
|
>>>
import
os
>>> os.linesep
'\r\n'
>>> os.sep
'\\'
>>> os.pathsep
';'
>>> os.curdir
'.'
>>> os.pardir
'..'
|
不过另外需要注意的是,print语句在输出时会自动为我们添加一个换行符,如果不需要该换行符,可以在输出语句后面加一个逗号','。
4.文件内建属性
主要如下:
文件对象的属性 | |
属性 | 描述 |
flie.closed | 如果文件已经关闭返回True,否则返回False |
file.encoding | 文件所使用的编码——当Unicode字符串被写入数据时,它们将自动使用file.encoding转换为字节字符串;若file.encoding为None时使用系统默认编码 |
file.mode | 文件打开时使用的访问模式 |
file.name | 文件名 |
file.newlines | 未读取到行分隔符时为None, 只有一种行分隔符时为一个字符串,当文件有多种类型的行结束符时,则为一个包含所有当前所遇到的行结束符的列表 |
file.softspace | 为0表示在输出一数据后,要加上一个空格符,1表示不加。这个属性一般程序员用不着,由程序内部使用 |
举例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> f
=
open
(
'test.txt'
,
'r+'
)
>>> f.read()
'xpleaf\nclyyh\ncl'
>>> f.closed
False
>>> f.encoding
>>> f.mode
'r+'
>>> f.name
'test.txt'
>>> f.newlines
>>> f.softspace
0
|
但是可以看到的是,newlines并没有任何输出。
5.标准文件
只要Python程序一执行,其实就可以访问到下面的这三个标准文件:
-
标准输入:键盘或磁盘的输入
-
标准输出:到显示器的缓冲输出
-
标准错误:到屏幕的非缓冲输出
注意上面的缓冲指的是open()的第三个参数,而之所以说程序一执行就可以访问这3个标准文件,是因为这些文件预先已经被打开了,只要知道它们的文件句柄主可以随时访问这些文件,Python中可以通过sys模块来访问这些文件的句柄:
-
sys.stdin
-
sys.stdout
-
sys.stderr
print语句通常是输出到sysy.stdout,而raw_input()则通常是从sys.stdin接收输入,如下:
1
2
3
4
5
6
|
>>>
import
sys
>>> sys.stdout.write(
'xpleaf\n'
)
xpleaf
>>> sys.stdin.readline()
xpleaf
'xpleaf\n'
|
其实上面的三个模块的属性也是file文件类型:
1
2
3
4
5
6
|
>>>
for
stream
in
[sys.stdin, sys.stdout, sys.stderr]:
...
print
type
(stream)
...
<
type
'file'
>
<
type
'file'
>
<
type
'file'
>
|
6.命令行参数
在C语言中有argc和argv两个变量,分别代表参数个数和参数向量,在Python中,argc其实就是sys.argv列表的长度,而该列表的第一项sys.argv[0]永远是程序的名称。举例如下:
程序代码:
1
2
3
4
5
6
|
#!/usr/bin/env python
import
sys
print
'you entered'
,
len
(sys.argv),
'arguments...'
print
'they were'
,
str
(sys.argv)
|
执行结果:
1
2
3
|
xpleaf@leaf:~$ python argv.py xpleaf clyyh cl
you entered
4
arguments...
they were [
'argv.py'
,
'xpleaf'
,
'clyyh'
,
'cl'
]
|
PYthon中关于命令行参数处理的模块如下:
-
getopt模块:不是很精细,但是简单
-
optparse模块:功能强大,更面向对象
7.文件系统
Python对文件系统的访问通过os模块实现,该模块是Python访问操作系统功能的主要接口,但不是真正的接口,真正的接口是由操作系统提供的,所以可以有如下的关系:
Python程序—os模块—操作系统文件系统接口模块(由os模块根据不同的操作系统进行选择)
而最常用的是os和os.path,这两个模块提供了与平台和操作系统无关的统一文件系统访问方法,如下:
-
os模块
os模块的文件/目录访问函数 | |
函数 | 描述 |
文件处理 | |
mkfifo()/mknod() | 创建命名管道/创建文件系统节点 |
remove()/unlink() | 删除文件 |
rename()/renames() | 重命名文件 |
stat(),lstat(),xstat() | 返回文件信息 |
symlink() | 创建符号链接 |
utime() | 更新时间戳 |
tmpfile() | 创建并打开('w+b')一个新的临时文件 |
目录/文件夹 | |
chdir()/fchdir() | 改变当前工作目录/通过一个文件描述符改变当前工作目录 |
chroot() | 改变当前进程的根目录 |
listdir() | 列出指定目录的文件 |
getcwd()/getcwdu() | 返回当前工作目录/功能相同,但返回一个Unicode对象 |
mkdir()/makedirs() | 创建目录/创建多层目录 |
rmdir()/removedirs() | 删除目录/删除多层目录 |
访问/权限 | |
access() | 检验权限模式 |
chmod() | 改变权限模式 |
chown()/lchown() | 改变owner和group ID/功能相同,但不会跟踪链接 |
umask() | 设置默认权限模式 |
文件描述符操作 | |
open() | 底层的操作系统open(对于文件,使用标准的内建open()函数) |
read()/write() | 根据文件描述符读取/写入数据 |
dup()/dup2() | 复制文件描述符号/功能相同,但是是复制到另一个文件描述符 |
设备号 | |
makedev() | 从major和minor设备号创建一个原始设备号 |
major()/minor() | 从原始设备号获得major/minior设备号 |
-
os.path模块
os.path模块中的路径名访问函数 | |
函数 | 描述 |
分隔 | |
basename() | 去掉目录路径,返回文件名 |
dirname() | 去年文件名,返回目录路径 |
join() | 将分离的各部分组合成一个路径名 |
split() | 返回(dirname(), basename())元组 |
splitdrive() | 返回(dirname, pathname)元组 |
splitext() | 返回(filename, extension)元组 |
信息 | |
getatime() | 返回最近访问时间 |
getctime() | 返回文件创建时间 |
getmtime() | 返回最近文件修改时间 |
getsize() | 返回文件大小(以字节为单位) |
查询 | |
exists() | 指定路径(文件或目录)是否存在 |
isabs() | 指定路径是否为绝对路径 |
isdir() | 指定路径是否存在且为一个目录 |
isfile() | 指定路径是否存在且为一个文件 |
islink() | 指定路径是否存在且为一个符号链接 |
ismount() | 指定路径是否存在且为一个挂载点 |
samefile() | 两个路径名是否指向同一个文件 |
关于os和os.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
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
|
#!/usr/bin/env python
import
os
for
tmpdir
in
(
'/tmp'
, r
'c:\temp'
):
if
os.path.isdir(tmpdir):
break
else
:
print
'no temp directory available'
tmpdir
=
''
if
tmpdir:
os.chdir(tmpdir)
cwd
=
os.getcwd()
print
'*** current temporary directory'
print
cwd
print
'*** creating example directory...'
os.mkdir(
'example'
)
os.chdir(
'example'
)
cwd
=
os.getcwd()
print
'*** new working directory: '
print
cwd
print
'*** original directory listing: '
print
os.listdir(cwd)
print
'*** creating test file...'
fobj
=
open
(
'test'
,
'w'
)
fobj.write(
'foo\n'
)
fobj.write(
'bar\n'
)
fobj.close()
print
'*** updated directory listing: '
print
os.listdir(cwd)
print
"*** renaming 'test' to 'filetest.txt' "
os.rename(
'test'
,
'filetest.txt'
)
print
'*** updated directory listing: '
print
os.listdir(cwd)
path
=
os.path.join(cwd, os.listdir(cwd)[
0
])
print
'*** full file pathname'
print
path
print
'*** (pathname, basename) =='
print
os.path.split(path)
print
'*** (filename, extension) =='
print
os.path.splitext(os.path.basename(path))
print
'*** displaying file contents: '
fobj
=
open
(path)
for
eachLine
in
fobj:
print
eachLine,
fobj.close()
print
'*** deleting test file'
os.remove(path)
print
'*** updated directory listing: '
print
os.listdir(cwd)
os.chdir(os.pardir)
print
'*** deleting test directory'
os.rmdir(
'example'
)
print
'*** DONE'
|
在Linux操作系统执行如下:
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
|
xpleaf@leaf:~$ python ospathex.py
*** current temporary directory
/tmp
*** creating example directory...
*** new working directory:
/tmp/example
*** original directory listing:
[]
*** creating
test
file
...
*** updated directory listing:
[
'test'
]
*** renaming
'test'
to
'filetest.txt'
*** updated directory listing:
[
'filetest.txt'
]
*** full
file
pathname
/tmp/example/filetest
.txt
*** (pathname,
basename
) ==
(
'/tmp/example'
,
'filetest.txt'
)
*** (filename, extension) ==
(
'filetest'
,
'.txt'
)
*** displaying
file
contents:
foo
bar
*** deleting
test
file
*** updated directory listing:
[]
*** deleting
test
directory
*** DONE
|
在Windows操作系统上执行如下:
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
|
C:\Users\xpleaf\Source_code>python ospathex.py
*** current temporary directory
c:\temp
*** creating example directory...
*** new working directory:
c:\temp\example
*** original directory listing:
[]
*** creating test file...
*** updated directory listing:
[
'test'
]
*** renaming
'test'
to
'filetest.txt'
*** updated directory listing:
[
'filetest.txt'
]
*** full file pathname
c:\temp\example\filetest.txt
*** (pathname, basename) ==
(
'c:\\temp\\example'
,
'filetest.txt'
)
*** (filename, extension) ==
(
'filetest'
,
'.txt'
)
*** displaying file contents:
foo
bar
*** deleting test file
*** updated directory listing:
[]
*** deleting test directory
*** DONE
|
8.文件执行
关于如何启动其他程序,以及如何与它们进行通信,或者是Python执行环境的一般信息,可以参考《Python回顾与整理12:执行环境》。
9.永久存储模块
以二进制数据的形式来存储Python的复杂数据结构(如列表、字典等),主要是pickle和json,其它的在需要用到时查阅即可。
10.相关模块
在需要使用时查阅即可。
本文转自 xpleaf 51CTO博客,原文链接:http://blog.51cto.com/xpleaf/1757262,如需转载请自行联系原作者