在python 3.3中将字符串写入文件失败

时间:2013-02-05 19:20:25

标签: python regex python-3.x file-io python-requests

我正在使用此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}},语法是正确的。 你能否指出我在这段代码中犯过的任何错误?

1 个答案:

答案 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的错误,以及该功能为何有用。所以,我想很多开发人员都不知道这一点是可以理解的。