如何在Python中迭代文件

52
我有一个包含十六进制数字的文本文件,我想将其转换为十进制。我成功地进行了转换,但似乎在循环结束之前它读取了一些不需要的字符,因此我遇到了以下错误。
Traceback (most recent call last):
  File "convert.py", line 7, in <module>
    print >>g, int(x.rstrip(),16)
ValueError: invalid literal for int() with base 16: ''

我的代码如下:

f=open('test.txt','r')
g=open('test1.txt','w')
#for line in enumerate(f):  
while True:
    x=f.readline()
    if x is None: break
    print >>g, int(x.rstrip(),16)

每个十六进制数字都需要单独一行输入


好的,请使用调试器查找导致问题的“x”值是多少。也许你有一个带BOM的文件? - user2665694
@RestRisiko:如果有BOM,错误消息会显示出来。但是没有,它只是试图将空字符串''传递给int。 - user395760
5个回答

78

回溯信息显示你的文件末尾可能有一个空行。 你可以这样修复:

f = open('test.txt','r')
g = open('test1.txt','w') 
while True:
    x = f.readline()
    x = x.rstrip()
    if not x: break
    print >> g, int(x, 16)

另一方面,最好使用for x in f而不是readline。不要忘记关闭文件或最好使用with来自动关闭它们:

with open('test.txt','r') as f:
    with open('test1.txt','w') as g: 
        for x in f:
            x = x.rstrip()
            if not x: continue
            print >> g, int(x, 16)

24
在更新的版本中,后者的缩进重量可以被减少:with open('test.txt', 'r') as f, open('test1.txt', 'w') as g - user395760
5
@delnan,很棒的新功能!当缩进不是问题时,我仍然更喜欢两行的形式。我读起来更清晰... - joaquin
1
哎呀!为什么会被踩呢?特别是当楼主已经接受了答案的时候,没有解释的踩是没有用的。 - joaquin
1
第一个程序如果在结尾处有空行,会出现相同的错误。 - user567879
我不明白。如果你的文本中有任何空行,x 就会变成 '',所以 'if not x' 防止了 print 的执行。请注意,我将你的 'if x is None' 改为了 'if not x'。 - joaquin
4
这是Python的"简洁性"范例,不需要EOF、readline()、writeline()或其他复杂操作,只需使用一个概念:遍历一个文件的每一行,进行转换并导出到另一个文件。非常好!(+1) - Assad Ebrahim

14
只需使用for x in f: ...,这会给你逐行读取,代码更短更易读(部分原因是它在文件结束时自动停止),并且还可以省去rstrip调用,因为尾随的换行符已经被剥离。
错误是由退出条件引起的,它永远不可能为真:即使文件耗尽,readline也会返回一个空字符串,而不是None。还要注意,您仍然可能遇到空行的问题,例如在文件末尾。添加if line.strip() == "": continue使代码忽略空行,这可能是个好主意。

4
这并不会剥离掉结尾的换行符:在Python 2.7.12和3.4.5上,python -c 'with open("file.txt") as f: print(repr([l[-1] for l in f]))'会返回许多\n实例。 - JamesTheAwesomeDude

7
with open('test.txt', 'r') as inf, open('test1.txt', 'w') as outf:
    for line in inf:
        line = line.strip()
        if line:
            try:
                outf.write(str(int(line, 16)))
                outf.write('\n')
            except ValueError:
                print("Could not parse '{0}'".format(line))

Hugh - outf.write(int(line, 16)) 对你有效吗?我的代码与你的完全相同,只是我试图写一个字典d。我得到了一个ValueError。请看下面:Traceback(最近的调用最先): 文件“./test.py”,第22行,在<module>中 outf.write(d) ValueError:在关闭的文件上进行I/O操作 - blehman

2
你应该学习EAFPLBYL的区别。
from sys import stdin, stdout
def main(infile=stdin, outfile=stdout):
    if isinstance(infile, basestring):
        infile=open(infile,'r')
    if isinstance(outfile, basestring):
        outfile=open(outfile,'w')
    for lineno, line in enumerate(infile, 1):
        line = line.strip()
         try:
             print >>outfile, int(line,16)
         except ValueError:
             return "Bad value at line %i: %r" % (lineno, line)

if __name__ == "__main__":
    from sys import argv, exit
    exit(main(*argv[1:]))

1
这可能是因为您的输入文件末尾有一个空行。 请尝试这样做:
for x in f:
    try:
        print int(x.strip(),16)
    except ValueError:
        print "Invalid input:", x

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接