简体   繁体   English

从Python中的文本文件读取文本时出现格式问题?

[英]Formatting issue from reading in text from text file in Python?

So, one of my assignments is to modify an existing trivia game so that each question has a certain point value. 因此,我的任务之一是修改现有的琐事游戏,以使每个问题都具有一定的分值。 The game gets pretty much all the text from a text file. 游戏几乎从文本文件中获取所有文本。

But, I'm having some issues: For some reason, when I add a point value to the text file, it messes up the format of the program and doesn't print some of the lines. 但是,我遇到了一些问题:由于某种原因,当我在文本文件中添加一个点值时,它弄乱了程序的格式,并且不打印某些行。

When I run it I get this: 当我运行它时,我得到以下信息:

    Welcome to Trivia Challenge!

    An Episode You Can't Refuse

  On the Run With a Mamma

  You'll end up on the goat

  1 - 

  2 - If you wait too long, what will happen?

  3 - You'll end up on the sheep

  4 - 

What's your answer?: 

I'm not sure how to fix it. 我不确定如何解决。 Any help? 有什么帮助吗?

Here's both the program file and the text file. 这是程序文件和文本文件。

# Trivia Challenge
# Trivia game that reads a plain text file

import sys

def open_file(file_name, mode):
    """Open a file."""
    try:
        the_file = open(file_name, mode)
    except(IOError), e:
        print "Unable to open the file", file_name, "Ending program.\n", e
        raw_input("\n\nPress the enter key to exit.")
    sys.exit()
    else:
        return the_file

def next_line(the_file):
    """Return next line from the trivia file, formatted."""
    line = the_file.readline()
    line = line.replace("/", "\n")
    return line

def next_block(the_file):
    """Return the next block of data from the trivia file."""
       category = next_line(the_file)

       question = next_line(the_file)

       answers = []
       for i in range(4):
           answers.append(next_line(the_file))

       correct = next_line(the_file)
       if correct:
           correct = correct[0]

       explanation = next_line(the_file)

       point_val = next_line(the_file)

       return category, question, answers, correct, explanation, point_val

def welcome(title):
    """Welcome the player and get his/her name."""
    print "\t\tWelcome to Trivia Challenge!\n"
    print "\t\t", title, "\n"

def main():
    trivia_file = open_file("trivia2.txt", "r")
    title = next_line(trivia_file)
    welcome(title)
    score = 0


  # get first block
    category, question, answers, correct, explanation, point_val = next_block(trivia_file)

    while category:
        # ask a question
        print category
        print question
        for i in range(4):
            print "\t", i + 1, "-", answers[i]

        # get answer
        answer = raw_input("What's your answer?: ")

        # check answer
        if answer == correct:
            print "\nRight!",
            score += int(point_val)
        else:
            print "\nWrong.",
        print explanation
        print "Score:", score, "\n\n"

        # get next block
        category, question, answers, correct, explanation, point_val = next_block(trivia_file)

    trivia_file.close()

    print "That was the last question!"
    print "You're final score is:", score

main()  
raw_input("\n\nPress the enter key to exit.")

Text File (trivia2.txt) 文字档(trivia2.txt)

An Episode You Can't Refuse 你不能拒绝的情节

On the Run With a Mamma 妈妈奔跑

If you wait too long, what will happen? 如果等待太久,会发生什么?

You'll end up on the sheep 你最终会陷入困境

You'll end up on the cow 你最终会牛

You'll end up on the goat 你最终会遇到山羊

You'll end up on the emu 您将进入the

A lamb is just a young sheep. 羔羊只是小羊。

5

The Godfather Will Get Down With You Now 教父现在会和你在一起

Let's say you have an audience with the Godfather of Soul. 假设您有灵魂教父的观众。 How would it be /smart / smart怎么样

to address him? 向他讲话?

Mr. Richard 理查德先生

Mr. Domino 多米诺先生

Mr. Brown 布朗先生

Mr. Checker 方格先生

10 10

James Brown is the Godfather of Soul. 詹姆斯·布朗(James Brown)是灵魂的教父。

That's Gonna Cost Ya 那将要花费你

If you paid the Mob protection money in rupees, what business would you most 如果您以卢比支付了暴民保护资金,那么您最会从事什么业务

likely be insuring? 可能会保险?

Your tulip farm in Holland 您在荷兰的郁金香农场

Your curry powder factory in India 您在印度的咖喱粉工厂

Your vodka distillery in Russian 您的伏特加酒厂用俄语

Your army knife warehouse in Switzerland 您在瑞士的军刀仓库

The Rupee is the standard monetary unit of India. 卢比是印度的标准货币单位。

15 15

Keeping It the Family 保持家庭

If your mother's father's sister's son was in "The Family," how are you related to the mob? 如果您母亲的父亲的姐姐的儿子在“家庭”中,您与暴徒有什么关系?

By your first cousin once removed 由您的第一个表亲移除

By your first cousin twice removed 由您的表弟两次删除

By your second cousin once removed 由你的第二个表亲移除

By your second cousin twice removed 被你的第二个堂兄两次删除

Your mother's father's sister is her aunt -- and her son is your mother's first cousin. 您母亲的父亲的姐姐是她的姑姑-儿子是您母亲的第一个表亲。 Since you and your mother are exactly one generation apart,her first cousin is your first cousin once removed. 由于您和您的母亲相差了一代人,她的第一个表亲是您的第一个表亲。

20 20

A Maid Man 女仆

If you were to literally launder your money, but didn't want the green in your bills to run, what temperature should you use? 如果您要从字面上洗钱,但又不想让钞票上的绿色运行,那么应该使用什么温度?

Hot

Warm

Tepid 不温不火

Cold

According to my detergent bottle, cold is best for colors that might run. 根据我的洗涤剂瓶,对于可能出现的颜色而言,最好使用冷水。

25 25

I'm not entirely sure what problem you're having, so I'm going to offer you some general comments on your code, in hopes that a better approach will lead you to a better result. 我不确定您遇到了什么问题,因此我将向您提供一些有关代码的一般注释,希望更好的方法可以使您获得更好的结果。

In general, when doing I/O, try to open and close the file as close together as possible so you don't forget to close it, and so the whole program is easier to debug. 通常,在执行I / O时,请尝试以尽可能靠近的方式打开和关闭文件,以免忘记关闭文件,从而使整个程序更易于调试。 Python makes this really easy for you if you can use the with statement as a context manager . 如果您可以将with语句用作上下文管理器, Python将为您提供真正的便利。

with open('filename.txt', 'r') as filename:
    some_var = filename.read()

After this block, filename is automatically closed for you, and some_var still has its entire contents as a string. 在该块之后,文件some_var自动为您关闭, some_var的全部内容仍为字符串。

Second, while I think it's really cool that you're using functions in this way to abstract bits of your code (this is a worthwhile approach!), I think you should abstract things that are a bit more specific to your problem set. 其次,虽然我认为以这种方式使用函数来抽象代码的部分真的很酷 (这是一种值得的方法!),但我认为您应该抽象一些对问题集更为特定的东西。 For instance, 例如,

def open_file(file_name, mode):
    """Open a file."""
    try:
        the_file = open(file_name, mode)
    except(IOError), e:
        print "Unable to open the file", file_name, "Ending program.\n", e
        raw_input("\n\nPress the enter key to exit.")
        sys.exit()
    else:
        return the_file

This function of yours takes a filename as a parameter and a mode argument and tries to open a file, and deals with an IOError in case it can't be opened. 您的此功能将文件名作为参数和模式参数,并尝试打开文件,并在无法打开文件的情况下处理IOError Sounds an awful lot like the built-in open , doesn't it? 听起来很像内置的open ,不是吗? So just use that! 因此,只需使用它! If you need to handle the IOError , you can do that in a normal try / except block, but sometimes it's OK to just let it bubble up. 如果您需要处理IOError ,则可以在正常的try / except块中执行此操作,但是有时可以让它冒泡。 After all, your program isn't really handling the exception, it's just reporting it then exiting, which is exactly what would have happened had you not caught it. 毕竟,您的程序并没有真正处理该异常,它只是报告该异常然后退出,如果您没有捕获到该异常,这正是发生的情况。 (Additionally, it would be more proper to re-raise the Exception or at least print your error message to sys.stderr , but that's another story.) (另外,重新引发Exception或至少将错误消息打印到sys.stderr会更合适,但这是另一回事了。)

The last thing I want to impart to you is about data structures. 我要向您介绍的最后一件事是关于数据结构的。 When I see your data blocks, here's what I see: 当我看到您的数据块时,就会看到以下内容:

{
    'category': line1,
    'question': line2,
    'answers': [line3, line4, line5, line6],
    'correct_answer': line7,
    'points': int(line7.strip()),
}

Each block is a dict grouping one set of data for a question. 每个块是一个dict将一个问题的一组数据分组。 If you stored this as q you could then call q['category'] , q[answers][0] , and the like. 如果将其存储为q ,则可以调用q['category']q[answers][0]等。 This groups things together in a more natural way than your tuple (which also requires you to repeat the line category, question, answers, correct, explanation, point_val = next_block(trivia_file) ). 这比元组更自然地将事物组合在一起(这也要求您重复行category, question, answers, correct, explanation, point_val = next_block(trivia_file) )。 Notice I have also grouped the answers into a list -- it's a list of answers! 注意,我也将答案分组到一个list -这是答案列表! You can put each such dict in a list (a list of dicts), then you have your whole set of trivia questions. 您可以将每个这样的dict放在一个列表(字典列表)中,然后您便拥有了一整套琐事问题。 You can even randomize the order by using random.shuffle on the whole list! 您甚至可以通过在整个列表上使用random.shuffle将顺序随机化!

Try reorganizing your file so that you do one thing at a time. 尝试重新组织文件,以便一次执行一件事。 Read the file, get what you want from it, then be done with it . 读取文件,从文件中获取所需内容,然后完成操作 Don't stretch the read operation over the entire script. 不要将读取操作扩展到整个脚本。 Parse out the questions, store them somewhere useful (hint: have you thought about making this a class?), then be done with it . 解析问题,将其存储在有用的地方(提示:您是否考虑过将它作为一个类?),然后再完成 Then loop through the already structured questions and ask away. 然后遍历已经结构化的问题并提出。 This will make your programs easier to debug and your life easier. 这将使您的程序更易于调试,生活也更轻松。 Might even help with what you have now. 甚至可能对您现在拥有的东西有所帮助。 :) :)


Quick Example 快速范例

"""Trivia challenge example"""

from __future__ import print_function, with_statement

import sys


questions = []
with open('trivia_file.txt', 'r') as trivia_file:
    title = trivia_file.readline()
    line = trivia_file.readline()
    while line:
        q = {}
        q['category'] = line
        q['question'] = trivia_file.readline()
        if q['question'].endswith('/'):
            q['question'] = q['question'][:-1] + trivia_file.readline()
        q['answers'] = [trivia_file.readline() for i in range(4)]
        q['correct'] = trivia_file.readline()
        q['explanation'] = trivia_file.readline()
        q['points'] = int(trivia_file.readline())
        questions.append(q)
        line = trivia_file.readline()

I was actually thinking you might read it in something like this. 我实际上是在想您可能会以这种方式阅读它。 There are certainly prettier ways to iterate through a file in Python, but for you every line is not meaningful, every several lines is, so this is arguably clearer. 当然,有很多更好的方法可以遍历Python中的文件,但是对您来说,每一行都没有意义,每行都是有意义的,因此可以说这很清楚。 (Also you have to deal with that bad line continuation syntax; better if that wasn't there, but I don't think you established the file formatting.) (此外,您还必须处理这种糟糕的行继续语法;如果不存在这种情况,则更好;但我认为您没有建立文件格式。)

Just read the file in, parse its contents, and move on. 只需读入文件,解析其内容,然后继续。 Now it's in memory and will close in the background. 现在它已在内存中,并且将在后台关闭。 You're ready to play trivia. 您已经准备好玩琐事。 All the dicts I described before are grouped in a nice long list now, so you can just randomize them: 我之前描述的所有字典现在都归为一个很长的列表,因此您可以将它们随机化:

import random
# if the questions are supposed to stay in order skip this step
random.shuffle(questions)

then play the game by iterating over them: 然后遍历它们来玩游戏:

for question in questions:
    print('Next category: ', question['category'])
    print('Q: ', question['question'])
    print('The possible answers are:')
    for i in range(4):
        print('{}. {}'.format(i+1, question['answers'][i]))
    # etc...

This will ask each question once. 这将询问每个问题一次。 Once you reach the end of the list, you are out of questions, so it's time for the game to end! 一旦您到达列表的末尾,就没有问题了,现在该游戏结束了!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM