我正在使用此python代码从给定文件(source_file.txt)中提取电子邮件地址,并将这些电子邮件地址写入单独的文件中。 (我正在使用python 3.3)
import urllib.request
import re
import fileinput, glob, string, sys, os
from os.path import join
import os
filePath = "source_file.txt"
if not filePath:
print("Sorry! Source File could not be located!")
else:
page = open(filePath, "r")
pageContent = page.read()
page.close()
style_normal = re.compile("[-a-zA-Z0-9._]+@[-a-zA-Z0-9_]+.[a-zA-Z0-9_.]+")
style_text_one = re.compile('[-a-zA-Z0-9._]+\s+at\s+[-a-zA-Z0-9_]+\s+dot\s+[a-zA-Z0-9_.]+')
style_text_two = re.compile('[-a-zA-Z0-9._]+\(at\)[-a-zA-Z0-9_]+\(dot\)[a-zA-Z0-9_.]+')
style_normal_list = style_normal.findall(str(pageContent))
style_text_one_list = style_text_one.findall(str(pageContent))
style_text_two_list = style_text_two.findall(str(pageContent))
f = open('emails_file.txt', 'a')
f.write('testing')
for item in style_normal_list:
print("%s" %item)
f.write("%s" %item)
for item in style_text_one_list:
text_one = item.replace(' at ','@')
text_two = text_one.replace(' dot ','.')
print(text_two)
f.write(text_two)
for item in style_text_two_list:
text_one = item.replace('(at)','@')
text_two = text_one.replace('(dot)','.')
f.write(text_two)
问题在于,当我运行此文件时,文件会被创建,但文件中没有任何内容。甚至没有文字'测试'。文件已创建,但它是空白的。
我使用print语句来检查代码的其他部分是否正常工作。 根据{{3}},语法是正确的。 你能否指出我在这段代码中犯过的任何错误?
答案 0 :(得分:2)
当您在文件上调用write
时,数据实际上不会立即写入磁盘,而是存储在缓冲区中。每隔一段时间,缓冲区就会被刷新。如果你想控制它,你可以明确地调用flush
,但通常最好不要 - 当你close
文件时,它会自动刷新。
但是你必须close
该文件才能正常工作。当文件对象被删除时,它会自行关闭,但您不能依赖于在任何特定时间甚至永远删除文件对象。 (您可以在CPython 2.7,CPython 3.3,IronPython等中了解它的工作原理,以及CPython 3.3如何处理在Unix与Windows上的不同退出等等,但您仍然不希望依赖这些的信息。)
因此,如果您在代码末尾添加一个明确的f.close()
,那么几乎解决了问题......但并非完全解决了。如果其他一些行引发异常怎么办?然后它永远不会进入close()
电话。
您可以使用try
/ finally
解决此问题,但有更好的方法,with
声明:
with open('emails_file.txt', 'a') as f:
f.write('testing')
# ...
for item in style_text_two_list:
text_one = item.replace('(at)','@')
text_two = text_one.replace('(dot)','.')
f.write(text_two)
这保证了一旦到达缩进的with
块的末尾 - 即使由于异常而发生,或者退出程序(或return
来自函数,如果你正处于一个函数中,或者break
来自循环,如果你处于循环中,等等,)f
将被关闭。
这在官方教程的Methods of File Object中都有解释,但是看看它是如何解释的,我可以想象很多新的程序员都不会从编写的内容中得到任何结果。 with statement
文档只有在你已经理解它的作用时才真正有意义,同样对于缓冲文件对象的解释... PEP 343,它引入了with
语句更好一点,但它花了很多时间来讨论前两个相关PEP的错误,以及该功能为何有用。所以,我想很多开发人员都不知道这一点是可以理解的。