这一节的内容是将一个文件中的内容复制到另外一个文件中。

书中在运行脚本时用echo创建了一个新的test.txt文件:

This is a test file.

但是我在实际运行时总是报错:

> echo "This is a test file." >ex17_test.txt
> cat ex17_test.txt
This is a test file.
> python .\ex17.py ex17_test.txt new-file.txt
Copying from ex17_test.txt to new-file.txt
Traceback (most recent call last):
File ".\ex17.py", line 10, in 
indata=in_file.read()
UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 0: illegal multibyte sequence

在网上找了一天原因都找不到,尝试了将powershell文件编码格式临时修改为UTF-8 chcp 65001也不行,在知乎上提问也被当作「代为完成个人任务」而关闭。希望能有知乎大神看到这篇文章告诉我到底是怎么回事。

更多文件操作:

from sys import argv #引入sys模块
from os.path import exists #引入os.path模块
script,from_file,to_file=argv #解包参数,并赋值给变量script,from_file,to_file
print(f"Copying from{from_file}to{to_file}") #打印字符串
#We could do these two on one line,how?
in_file=open(from_file) #用open函数打开变量from_file,并赋值给变量in_file
indata=in_file.read() #在变量in_file后面调用read函数(读取文件内容),并把结果赋值给变量indata
print(f"The input file is {len(indata)} bytes long") #打印字符串,len()函数会以数值形式返回你传递的字符串的长度
print(f"Does the output file exist?{exists(to_file)}") #打印字符串
print("Ready,hit RETURN to continue,CTRL-C to abort.") #打印字符串
input() #接收输入内容
out_file=open(to_file,'w') #用open函数以写入模式打开变量to_file,并将该文件放入变量out_file的目录下,如无该文件将自动创建一个
out_file.write(indata) #在变量out_file后面调用write函数,写入变量indata的内容
print("Alright,all done.") #打印字符串
out_file.close() #在变量out_file后面调用close函数关闭文件
in_file.close() #在变量in_file后面调用close函数关闭文件

这里我用ex16创建的test.txt文件来运行脚本:

> python .\ex17.py test.txt new-file.txt
Copying from test.txt to new-file.txt
The input file is 71 bytes long
Does the output file exist?False
Ready,hit RETURN to continue,CTRL-C to abort.
Alright,all done.
> cat new-file.txt
Mary had a little lamb
It's fleece was white as snow
It was also tasty

新的new-file.txt文件内容:

Mary had a little lamb
It's fleece was white as snow
It was also tasty

加分习题:

Q1.这个脚本实在是有点烦人。没必要在做复制之前问你,也没必要在屏幕上输出那么多东西。试着删掉脚本的一些功能,让它使用起来更加友好。

友好的脚本:

from sys import argv
script,from_file,to_file=argv
indata=open(from_file).read() #用open函数打开变量from_file并读取文件内容,然后把结果赋值给变量indata
out_file=open(to_file,'w')
out_file.write(indata)
print(f"Alright,all done.The file is {len(indata)} bytes long.")

运行结果:

> python .\ex17_drills.py test.txt new-file.txt

Alright,all done.The file is 71 bytes long.

Q2.看看你能把这个脚本改多短,我可以把它变成一行。

看了网上很多大神的,我只能精简的3行

from sys import argv
script,from_file,to_file=argv
open(to_file,'w').write(open(from_file).read())#用open函数以写入模式打开变量to_file,并写入用open函数打开变量from_file读取文件的内容

运行结果:

> python .\ex17_drills.py test.txt new-file.txt

除了输入的指令外没有任何显示的内容,直接生成new-file.txt

Q3.在“应该看到的结果”中我使用了一个叫cat的东西,这个古老的命令的用途是将两个文件“拼接”到一起,不过实际上它最大的用途是打印文件内容到屏幕上。你可以通过man cat命令了解到更多信息。

> man cat

名称

Get-Content

语法

Get-Content [-Path] []

Get-Content []

别名

gc

cat

type

备注

Get-Help 在此计算机上找不到该 cmdlet 的帮助文件。它仅显示部分帮助。

-- 若要下载并安装包含此 cmdlet 的模块的帮助文件,请使用 Update-Help。

-- 若要联机查看此 cmdlet 的帮助主题,请键入: "Get-Help Get-Content -Online" 或

Q4.找出为什么需要在代码中写output.close()

这里我直接引用大神写的回答吧:原因在于如果不写,则新复制的文件中是不会保存任何内容的。

out_put = open(to_file, 'w') 执行时会创建 to_file 文件,但是没内容
out_put.write(indata) 执行时,内容会写入到 to_file 的内存数据中,但仍未写入硬盘。

只有在执行 close 时 python 才指定文本的各种操作已经结束了,不会再有任何变化,这个时候在写入硬盘可以尽可能地减少硬盘读写操作,提高效率(特别在特大文件的时候)

那么为什么在 精简练习、极限精简练习 中不需要关闭呢?

我的理解:

关键点在于没有使用变量,也就是没有个打开的文件起名字。

这个时候,任何操作是一次性的,我们没办法在写入了一些东西后再说“喂,就你,你再写入这些内容”,python 不知道这句‘喂’说的是哪一个内存堆栈中的数据。

所有没有其名的代码都是一次性的,不会保存在内存中,针对 open 来说,python 就自动关闭它了。

Q5.阅读一下与Python的import语句相关的内容,打开python测试一下。试着导入一些东西,看看你能不能弄对,弄不对也没关系。