【问题标题】:Python: How to properly use readline() and readlines()Python:如何正确使用 readline() 和 readlines()
【发布时间】:2019-05-23 23:07:13
【问题描述】:

按照Gödel, Escher, Bach 提供的图表,我已经构建了一个 Python 脚本来使用来自普林斯顿英语 Wordnet 的数据随机创建句子。调用python GEB.py 会生成一个无意义的英语句子列表,例如:

复苏的非审美成本。 苔藓植物的指甲。 厌恶第四十桃。 星光之皮。 翻译袍子的面粉拿了_a_dare一拳打穿了重新请求分封的applewood。 金枪鱼旁边的叶状货船。

并将它们保存到 gibberish.txt。该脚本运行良好。

另一个脚本 (translator.py) 使用 gibberish.txt,并通过 py-googletrans Python 模块尝试将这些随机句子翻译成葡萄牙语:

from googletrans import Translator
import json

tradutor = Translator()

with open('data.json') as dataFile:
    data = json.load(dataFile)


def buscaLocal(keyword):
    if keyword in data:
        print(keyword + data[keyword])
    else:
        buscaAPI(keyword)


def buscaAPI(keyword):
    result = tradutor.translate(keyword, dest="pt")
    data.update({keyword: result.text})

    with open('data.json', 'w') as fp:
        json.dump(data, fp)

    print(keyword + result.text)


keyword = open('/home/user/gibberish.txt', 'r').readline()
buscaLocal(keyword)

目前第二个脚本只输出 gibberish.txt 中第一句的翻译。比如:

复苏的非审美成本。 aumento de custos inestético。

我尝试使用readlines() 代替readline(),但出现以下错误:

Traceback (most recent call last):
  File "main.py", line 28, in <module>
    buscaLocal(keyword)
  File "main.py", line 11, in buscaLocal
    if keyword in data:
TypeError: unhashable type: 'list'

我在这里阅读过有关此错误的类似问题,但我不清楚应该使用什么来阅读 gibberish.txt 中包含的整个句子列表(新句子以新行开头)。

如何阅读 gibberish.txt 中包含的完整句子列表?我应该如何调整translator.py 中的代码以实现这一目标?如果问题有点混乱,我很抱歉,如有必要,我可以编辑,我是 Python 新手,如果有人可以帮助我,我将不胜感激。

【问题讨论】:

  • 请提供完整的错误消息,包括堆栈跟踪。我怀疑是readlines 导致了这个错误。相反,readlines 返回一个 list 行,您可能试图将该列表放入 dict 但您不能,因为列表对象不可散列。一般情况下,您需要提供minimal reproducible example
  • 特别是这里:data.update({keyword: result.text})
  • 刚刚编辑了完整的错误信息,很抱歉。
  • 好的,正如我所解释的,readlines 返回一个 list 对象,该对象不可散列,因此,它不能用作 dict 对象的键
  • 我明白了,所以 readlines() 根本不适合这里吗?感谢您的帮助。因此,使用代码 sn-p 中提供的 readline() 会输出句子列表中第一行的翻译。我应该改用什么来输出 .txt 中所有句子的翻译?

标签: python translation readline wordnet readlines


【解决方案1】:

如果您使用readline() 函数,您必须记住该函数只返回一行,因此您必须使用循环遍历文本文件中的所有行。如果使用readlines(),此函数会立即读取整个文件,但会返回列表中的每一行。列表数据类型是不可散列的,不能用作dict 对象中的键,这就是if keyword in data: 行发出此错误的原因,因为keyword 这里是所有行的列表。一个简单的 for 循环就可以解决这个问题。

text_lines = open('/home/user/gibberish.txt', 'r').readlines()
for line in text_lines:
     buscaLocal(line)

这个循环将遍历列表中的所有行,访问字典时会出错,因为关键元素将是一个字符串。

【讨论】:

  • 谢谢@arryph,就像一个魅力。抱歉问了这么一个基本的问题,有时你会卡在最原始的问题上。感谢您的帮助!
【解决方案2】:

让我们从您对文件对象所做的事情开始。您打开一个文件,从中获取一行,然后不要关闭它。更好的方法是处理整个文件然后关闭它。这通常使用with 块完成,即使发生错误也会关闭文件:

with open('gibberish.txt') as f:
    # do stuff to f

除了物质上的好处,这将使界面更加清晰,因为f 不再是一个一次性的对象。您可以通过三个简单的选项来处理整个文件:

  1. 在循环中使用readline,因为它一次只能读取一行。当'' 出现时,您必须手动删除换行符并终止循环:

    while True:
        line = f.readline()
        if not line: break
        keyword = line.rstrip()
        buscaLocal(keyword)
    

    这个循环可以有多种形式,这里展示了其中一种。

  2. 使用readlines 一次将文件中的所有行读入字符串列表:

    for line in f.readlines():
        keyword = line.rstrip()
        buscaLocal(keyword)
    

    这比前一个选项更简洁,因为您不需要手动检查循环终止,但它的缺点是一次加载整个文件,readline 循环没有。

    这将我们带到第三个选项。

  3. Python 文件是可迭代的对象。您可以享受readlines 方法的简洁性和readline 的内存节省:

    for line in f:
         buscaLocal(line.rstrip())
    

    可以使用readline 和更神秘的next 形式模拟这种方法,以创建类似的迭代器:

    for line in next(f.readline, ''):
         buscaLocal(line.rstrip())
    

顺便说一句,我会对你的函数做一些修改:

def buscaLocal(keyword):
    if keyword not in data:
        buscaAPI(keyword)
    print(keyword + data[keyword])

def buscaAPI(keyword):
    # Make your function do one thing. In this case, do a lookup.
    # Printing is not the task for this function.
    result = tradutor.translate(keyword, dest="pt")
    # No need to do a complicated update with a whole new
    # dict object when you can do a simple assignment.
    data[keyword] = result.text

...

# Avoid rewriting the file every time you get a new word.
# Do it once at the very end.
with open('data.json', 'w') as fp:
    json.dump(data, fp)

【讨论】:

  • 哇,这是一堂很棒的课。对于像我这样的初学者来说,这里有很多东西要学。我稍后会尝试这些,以使程序更高效,我会回复你。感谢您花时间写出如此详细的答案,非常感谢。
猜你喜欢
  • 2014-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-05
  • 2011-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多