1. 文件与文件路径
1.1 Windows上的倒斜杠以及OS X和Linux上的正斜杠
在Windows上, 路径书写使用倒斜杠作为文件夹之间的分隔符。但在OS X和linux上,使用正斜杠最为它们的路径分
隔符。如果想要程序运行在所有操作系统上, 在编写python脚本时,就必须处理这两种情况。
好在,用os.path.join()函数来做这件事很简单。如果将单个文件和路径上的文件夹名称的字符串传递给它,
os.path.join()就会返回一个文件路径的字符串, 包含正确的路径分隔符。
os.path.join('user','bin','spam')
'user\\bin\\spam'
在windows中运行为上例结果,注意是两个\\,其中一个用于转义。如果在linux中,则为:'user/bin/spam'
如果需要创建文件名称的字符串,os.path.join()函数就很有用。这些字符串将传递给几个文件相关的函数,下面的例
子将一个文件名列表中的名称,添加到文件夹名称的末尾。
import os
myFiles = ['accounts.txt', 'details.csv', 'invite.docx']
for filename in myFiles:
print(os.path.join('C:\\Users\\asweigart', filename))
C:\Users\asweigart\accounts.txt
C:\Users\asweigart\details.csv
C:\Users\asweigart\invite.docx
1.2 当前工作目录
每个运行在计算机上的程序, 都有一个“当前工作目录”。或cwd。所以没有从根文件夹开始的文件名或路径,都假
定在当前工作目录下。利用os.getcwd()函数,可以获得当前工作路径的字符串,并利用os.chdir()改变它。
import os
os.getcwd()
'D:\\Jupyter Notebook\\Python编程快速上手'
os.chdir('C:\\Windows\\System32')
os.getcwd()
'C:\\Windows\\System32'
如果要更改的当前工作目录不存在,Python就会显示一个错误。
os.chdir('C:\\dfgh')
FileNotFoundError Traceback (most recent call last)
<ipython-input-8-cff0e0f99e62> in <module>()
----> 1 os.chdir('C:\\dfgh')
FileNotFoundError: [WinError 2] 系统找不到指定的文件。: 'C:\\dfgh'
1.3 绝对路径和相对路径
有两种方法指定一个文件路径。
·绝对路径:总是从根文件夹开始。
·相对路径:从相对于程序的当前工作目录开始。
还有(.)和(..)文件夹。它们不是真正的文件夹,而是可以在路径中使用的特殊名称。单个的句点用作文件夹名称
时,是“这个目录”的缩写。两个句点意思是父文件夹。
1.4 用os.makedirs()创建新文件夹
程序可以用os.makedirs()函数创建新文件夹(目录)。
import os
os.makedirs('D:\\Jupyter Notebook\\test')
image.png
1.5 os.path模块
os.path模块包含了许多与文件名和文件路径相关的有用函数。例如,你已经使用了os.path.join()来构建所有操作系统
上都有效的路径。因为os.path是os模块中的模块,所以只要执行import os 就可以导入它。
1.6 处理绝对路径和相对路径
os.path模块提供了一些函数, 返回一个相对路径的绝对路径,以及检查给定的路径是否为绝对路径。
·调用os.path.abspath(path)将返回参数的绝对路径的字符串。这就将相对路径转换为绝对路径的简便方法。
·调用os.path.isabs(path),如果参数是一个绝对路径,就返回True,如果参数是一个相对路径,就返回False.
·调用os.path.relpath(path, start)将返回从start路径到path的相对路径的字符串。如果没有提供start, 就使用当前工作目录作为开始路径。
os.path.abspath('.')
'D:\\Jupyter Notebook\\Python编程快速上手'
os.path.abspath('.\\test')
'D:\\Jupyter Notebook\\Python编程快速上手\\test'
os.path.isabs('.')
False
os.path.isabs(os.path.abspath('.'))
True
>>> os.path.relpath('C:\\Windows', 'C:\\')
'Windows'
>>> os.path.relpath('C:\\Windows', 'C:\\spam\\eggs')
'..\\..\\Windows'
>>> os.getcwd()
'C:\\Python34'
调用os.path.dirname(path)将返回一个字符串,它包含path 参数中最后一个斜杠
之前的所有内容。调用os.path.basename(path)将返回一个字符串,它包含path 参数
中最后一个斜杠之后的所有内容。如下图所示:
image.png
path = 'D:\\pywork\\girl1.txt'
os.path.basename(path)
'girl1.txt'
os.path.dirname(path)
'D:\\pywork'
如果同时需要一个路径的目录名称和基本名称,就可以调用os.path.split(),获得这两个字符串的元组,像这样:
calcFilePath = 'D:\\pywork\\girl1.txt'
os.path.split(calcFilePath)
('D:\\pywork', 'girl1.txt')
请注意,可以调用os.path.dirname()和os.path.basename(),将它们的返回值放在一个元组中,从而得到同样的元组。
(os.path.dirname(calcFilePath), os.path.basename(calcFilePath))
('D:\\pywork', 'girl1.txt')
但如果需要两个值,os.path.split()是很好的快捷方式。
同时也请注意,os.path.split()不会接受一个文件路径并返回每个文件夹的字符串的列表。如果需要这样,请使用
split()字符串方法,并根据os.path.sep 中的字符串进行分割。回忆一下,根据程序运行的计算机,os.path.sep 变
量设置为正确的文件夹分割斜杠。
calcFilePath.split(os.path.sep)
['D:', 'pywork', 'girl1.txt']
split()字符串方法将返回一个列表,包含该路径的所有部分。如果向它传递os.path.sep,就能在所有操作系统上工作。
1.7 查看文件大小和文件夹内容
一旦有办法处理文件路径,就可以开始搜集特定文件和文件夹的信息。os.path 模块提供了一些函数,用于查看文
件的字节数以及给定文件夹中的文件和子文件夹。
• 调用os.path.getsize(path)将返回path 参数中文件的字节数。
• 调用os.listdir(path)将返回文件名字符串的列表,包含path 参数中的每个文件(请注意,这个函数在os 模块中,而不是os.path)。
os.path.getsize('D://pywork/passwd.py')
504
os.listdir('D://pywork/TXyiqing/')
['.idea', 'Include', 'Lib', 'pyvenv.cfg', 'Scripts', 'spider.py', 'SQLdb.py']
如果想知道TXyiqing文件夹中所有文件的总字节数,就可以同时使用os.path.getsize()和os.listdir()
totalSize = 0
for filename in os.listdir('D://pywork/TXyiqing/'):
totalSize = totalSize + os.path.getsize(os.path.join('D://pywork/TXyiqing/', filename))
print(totalSize)
54322
1.8 检查路径有效性
如果你提供的路径不存在,许多Python 函数就会崩溃并报错。os.path 模块提供了一些函数,用于检测给定的路径
是否存在,以及它是文件还是文件夹。
• 如果path 参数所指的文件或文件夹存在,调用os.path.exists(path)将返回True,否则返回False。
• 如果path 参数存在,并且是一个文件,调用os.path.isfile(path)将返回True,否则返回False。
• 如果path 参数存在,并且是一个文件夹,调用os.path.isdir(path)将返回True,否则返回False。
os.path.exists('C://Windows/')
True
os.path.exists('D://pywork//leon.txt')
False
os.path.isdir('D:\\pywork\\TXyiqing')
True
os.path.isfile('D:\\pywork\\TXyiqing')
False
os.path.isfile('D:\\pywork\\TXyiqing\\SQLdb.py')
True
os.path.isdir('D:\\pywork\\TXyiqing\\SQLdb.py')
False
2. 文件读写过程
在Python 中,读写文件有3 个步骤:
1.调用open()函数,返回一个File 对象。
2.调用File 对象的read()或write()方法。
3.调用File 对象的close()方法,关闭该文件。
2.1 用open()函数打开文件
要用open()函数打开一个文件,就要向它传递一个字符串路径,表明希望打开的文件。这既可以是绝对路径,也可
以是相对路径。open()函数返回一个File 对象。
helloFile = open('D://pywork/hello.txt')
这些命令都将以读取纯文本文件的模式打开文件,或简称为“读模式”。当文件以读模式打开时,Python 只让你从文
件中读取数据,你不能以任何方式写入或修改它。在Python 中打开文件时,读模式是默认的模式。但如果你不希
望依赖于Python 的默认值,也可以明确指明该模式,向open()传入字符串'r',作为第二个参数。所以
open('/Users/asweigart/hello.txt', 'r') 和 open('/Users/asweigart/hello.txt')做的事情一样。
调用open()将返回一个File 对象。File 对象代表计算机中的一个文件,它只是Python 中另一种类型的值,就像你已
熟悉的列表和字典。在前面的例子中,你将File对象保存在helloFile 变量中。现在,当你需要读取或写入该文件,
就可以调用helloFile 变量中的File 对象的方法。
2.2 读取文件内容
既然有了一个File 对象,就可以开始从它读取内容。如果你希望将整个文件的内容读取为一个字符串值,就使用
File 对象的read()方法。让我们继续使用保存在 helloFile 中的hello.txt File 对象。
helloContent = helloFile.read()
helloContent
'Hello World!'
如果你将文件的内容看成是单个大字符串,read()方法就返回保存在该文件中的这个字符串。或者,可以使用
readlines()方法,从该文件取得一个字符串的列表。列表中的每个字符串就是文本中的每一行.
sonnetFile = open('D:\\pywork\\pw.py')
sonnetFile.readlines()
['#! python3\n',
'#! pw.py - An insecure password locker program.\n',
'\n',
"PASSWORD = {'email': 'F7minwefrkdfksdjfi',\n",
" 'blog': 'VmALfsfjsdfhdsjhfusdhg', \n",
" 'luggage': '12345'}\n",
'\n',
'import sys, pyperclip\n',
'if len(sys.argv) < 2:\n',
" print('Usage: python pw.py [acount] - copy account password')\n",
' sys.exit()\n',
' \n',
'account = sys.argv[1] # first command line arg is the account name\n',
'\n',
'if account in PASSWORD:\n',
' pyperclip.copy(PASSWORD[account])\n',
" print('Password for ' + account + ' copied to clipboard.')\n",
'else:\n',
" print('There is no account named '+ account)"]
请注意, 每个字符串值都以一个换行符\n结束。除了文件的最后一行。
2.3 写入文件
Python 允许你将内容写入文件,方式与print()函数将字符串“写”到屏幕上类似。但是,如果打开文件时用读模式,
就不能写入文件。你需要以“写入纯文本模式”或“添加纯文本模式”打开该文件,或简称为“写模式”和“添加模式”。写
模式将覆写原有的文件,从头开始,就像你用一个新值覆写一个变量的值。将'w'作为第二个参数传递给open(),以
不同的是,添加模式将在已有文件的末尾添加文本。你可以认为这类似向一个变量中的列表添加内容,而不是完
全覆写该变量。将'a'作为第二个参数传递给open(),以添加模式打开该文件。
如果传递给 open()的文件名不存在,写模式和添加模式都会创建一个新的空文件。在读取或写入文件后,调用
close()方法,然后才能再次打开该文件。
baconFile = open('bacon.txt', 'w')
baconFile.write('Hello World!\n')
baconFile.close()
baconFile = open('bacon.txt', 'a')
baconFile.write('Bacon is not a vegetable.')
baconFile.close()
baconFile = open('bacon.txt')
content = baconFile.read()
baconFile.close
print(content)
Hello World!
Bacon is not a vegetable.
首先,我们以写模式打开bacon.txt。因为还没有bacon.txt,Python 就创建了一个。在打开的文件上调用write(),并
向write()传入字符串参数'Hello world! \n',将字符串写入文件,并返回写入的字符个数,包括换行符。然后关闭该
文件。(只有执行了close()文件才会显示更改后的内容,否则仍然显示未更改之前的内容)
为了将文本添加到文件已有的内容,而不是取代我们刚刚写入的字符串,我们就以添加模式打开该文件。向
该文件写入'Bacon is not a vegetable.',并关闭它。最后,为了将文件的内容打印到屏幕上,我们以默认的读模式
打开该文件,调用read(),将得到的内容保存在content 中,关闭该文件,并打印content。
请注意,write()方法不会像print()函数那样,在字符串的末尾自动添加换行字符。必须自己添加该字符。
3. 用shelve模块保存变量
利用shelve 模块,你可以将Python 程序中的变量保存到二进制的shelf 文件中。这样,程序就可以从硬盘中恢复变
量的数据。shelve 模块让你在程序中添加“保存”和“打开”功能。例如,如果运行一个程序,并输入了一些配置设
置,就可以将这些设置保存到一个shelf 文件,然后让程序下一次运行时加载它们。
import shelve
shelfFile = shelve.open('mydata')
cats = ['Zopjie', 'Pooka', 'Simon']
shelfFile['cats'] = cats
shelfFile.close()
要利用shelve 模块读写数据,首先要导入它。调用函数shelve.open()并传入一个文件名,然后将返回的值保存在
一个变量中。可以对这个变量的shelf 值进行修改,就像它是一个字典一样。当你完成时,在这个值上调close()。
这里,我们的shelf 值保存在shelfFile中。我们创建了一个列表cats,并写下shelfFile['cats'] =cats,将该列表
保存在shelfFile 中,作为键'cats'关联的值(就像在字典中一样)。然后我们在shelfFile 上调用close()。
在Windows 上运行前面的代码,你会看到在当前工作目录下有3 个新文件:mydata.bak、mydata.dat 和
mydata.dir。在OS X 上,只会创建一个mydata.db 文件。
这些二进制文件包含了存储在shelf 中的数据。这些二进制文件的格式并不重要,你只需要知道shelve 模块做了什
么,而不必知道它是怎么做的。该模块让你不用操心如何将程序的数据保存到文件中。
你的程序稍后可以使用shelve 模块,重新打开这些文件并取出数据。shelf 值不必用读模式或写模式打开,因为它们在打开后,既能读又能写。
import shelve
shelfFile = shelve.open('mydata')
type(shelfFile)
shelve.DbfilenameShelf
shelfFile['cats']
['Zophie', 'Pooka', 'Simon']
shelfFile.close()
这里,我们打开了shelf 文件,检查我们的数据是否正确存储。输入shelfFile['cats']将返回我们前面保存的同一个
列表,所以我们就知道该列表得到了正确存储,然后我们调用close()。
就像字典一样,shelf 值有keys()和values()方法,返回shelf 中键和值的类似列表的值。因为这些方法返回类似列
表的值,而不是真正的列表,所以应该将它们传递给list()函数,取得列表的形式。
就像字典一样,shelf 值有keys()和values()方法,返回shelf 中键和值的类似列表的值。因为这些方法返回类似列
表的值,而不是真正的列表,所以应该将它们传递给list()函数,取得列表的形式。
shelfFile = shelve.open('mydata')
list(shelfFile.keys())
['cats']
list(shelfFile.values())
[['Zophie', 'Pooka', 'Simon']]
shelfFile.close()
创建文件时,如果你需要在Notepad 或TextEdit 这样的文本编辑器中读取它们,纯文本就非常有用。但是,如果想
要保存Python 程序中的数据,那就使用shelve 模块。
4. pprint.pformat()函数保存变量
回忆一下“漂亮打印”中,pprint.pprint()函数将列表或字典中的内容“漂亮打印”到屏幕,而pprint.pformat()函
数将返回同样的文本字符串,但不是打印它。这个字符串不仅是易于阅读的格式,同时也是语法上正确的Python
代码。假定你有一个字典,保存在一个变量中,你希望保存这个变量和它的内容,以便将来使用。pprint.pformat()
函数将提供一个字符串,你可以将它写入.py 文件。该文件将成为你自己的模块,如果你需要使用存储在其中的变
量,就可以导入它。
import pprint
cats = [{'name': 'Zophie', 'desc': 'chubby'}, {'name': 'Pooka', 'desc': 'fluffy'}]
pprint.pformat(cats)
fileObj = open('myCats.py', 'w')
fileObj.write('cats =' + pprint.pformat(cats) + '\n')
fileObj.close()
这里,我们导入了pprint,以便能使用pprint.pformat()。我们有一个字典的列表,保存在变量cats 中。为了让cats
中的列表在关闭交互式环境后仍然可用,我们利用pprint.pformat(),将它返回为一个字符串。当我们有了cats 中数
据的字符串形式,就很容易将该字符串写入一个文件,我们将它命名为myCats.py。
import 语句导入的模块本身就是Python 脚本。如果来自pprint.pformat()的字符串保存为一个.py 文件,该文件就
是一个可以导入的模块,像其他模块一样。
由于Python 脚本本身也是带有.py 文件扩展名的文本文件,所以你的Python 程序甚至可以生成其他Python 程
序。然后可以将这些文件导入到脚本中。
import myCats
myCats.cats
[{'desc': 'chubby', 'name': 'Zophie'}, {'desc': 'fluffy', 'name': 'Pooka'}]
myCats.cats[0]
{'desc': 'chubby', 'name': 'Zophie'}
myCats.cats[0]['name']
'Zophie'
创建一个.py 文件(而不是利用shelve 模块保存变量)的好处在于,因为它是一个文本文件,所以任何人都可以
用一个简单的文本编辑器读取和修改该文件的内容。但是,对于大多数应用,利用shelve 模块来保存数据,是将变
量保存到文件的最佳方式。只有基本数据类型,诸如整型、浮点型、字符串、列表和字典,可以作为简单文本写入
一个文件。例如,File 对象就不能够编码为文本。