简体   繁体   English

如何从python中的文件制作元组列表

[英]how to make a list of tuples from a file in python

Ok I have a file like that looks like this. 好的,我有一个像这样的文件。

panite,1,1800
ruby,2,100
diamond,0.75,900
emerald,3,250
amethyst,2,50
opal,1,300
sapphire,0.5,750
benitoite,1,2000
malachite,1,60

Our teacher gave us code that uses a try/except to help us open the file. 我们的老师给了我们使用try / except的代码来帮助我们打开文件。 I need to open the file and read each line and make each line a tuple and then put it in a list. 我需要打开文件并阅读每一行,并将每一行设置为一个元组,然后将其放入列表中。 The list is supposed to be the last numbe divided by the middle number, and then that value followed by the name of the gem(the middle number is the carat of the gem). 该列表应该是最后一个数字除以中间的数字,然后是该值,然后是宝石的名称(中间的数字是宝石的克拉)。 The problem i'm having is I cant even get it to make a list from the file. 我遇到的问题是我什至无法从文件中列出列表。 This is what i've tried to open it without much success. 这就是我试图打开它没有太大的成功。

def main():
    fileFound = False
    while not fileFound:
        fileName = input('File name containing jewel data: ')
        try:
            dataFile = open(fileName, "r")
            fileFound = True
            knapsack()
        except:
            print ('Could not find that file -- try again')

def knapsack():
    list = dataFile.readline()

I've actually had a little success when I changed it to a simple printstatement under def knapsack() where it will print something simple like 2+2, but when I try to make a list, it gives me the except error instead. 当我在def knapsack()下将其更改为简单的printstatement时,我实际上取得了一些成功,该语句将打印2 + 2之类的简单内容,但是当我尝试创建列表时,它却给了我除外错误。 This is my first programming class so any insight into this would be appreciated. 这是我的第一门编程课,因此对此有任何见解将不胜感激。

def make_jewel(line):
    name, carats, price = line.split(",")
    return (float(price)/float(carats), name)

def main():
    while True:
        file_name = input('File name containing jewel data: ')
        try:
            with open(file_name) as inf:
                data = [make_jewel(line) for line in inf]
            break
        except FileNotFoundError:
            print('Could not find that file -- try again')

main()

and some comments: 和一些评论:

  • except: without a specified exception-type, also known as a "bare exception", is frowned on because it catches everything . except:没有指定的异常类型(也称为“裸异常”)之所以皱眉,是因为它捕获了所有内容 You should specify the type of exceptions you expect to see, and only handle those; 您应该指定希望看到的异常类型,并且仅处理这些异常。 if you catch everything and something totally unexpected fails (ie ComputerOnFireError !) you will never find out about it. 如果您捕获了所有内容,而完全出乎意料的失败(即ComputerOnFireError !),您将一无所获。

  • opening a file using with is preferred because it ensures the file will always get closed properly. 首选使用with来打开文件with因为它可以确保始终正确关闭文件。

  • when you open a file in text mode, you can iterate over it line-by-line; 当您以文本模式打开文件时,可以逐行对其进行遍历; this is the most common way to process a file. 这是处理文件的最常用方法。

  • when you .split() a string, you get a list of strings back. 当您使用.split()字符串时,您将获得一个字符串列表。 Before doing math on the pieces you have to convert them from a string to a numeric value using int() or float() . 在对片段进行数学运算之前,您必须使用int()float()将它们从字符串转换为数值。

Hope that helps. 希望能有所帮助。

Use the csv module to read lines as csv rows. 使用csv模块将行读取为csv行。

import csv

def knapsack(datafile):
    output_data = []
    csv_reader = csv.reader(datafile, delimiter=',')
    for row in csv_reader:
        output_data.append(tuple(row))
    return output_data

This will give you output_data as: 这将为您提供output_data为:

[('panite', '1', '1800'),
 ('ruby', '2', '100'),
 ('diamond', '0.75', '900'),
 ('emerald', '3', '250'),
 ('amethyst', '2', '50'),
 ('opal', '1', '300'),
 ('sapphire', '0.5', '750'),
 ('benitoite', '1', '2000'),
 ('malachite', '1', '60')]

which is a list of tuples. 这是一个元组列表。 This solves your problem of making a list from the file. 这解决了从文件中列出列表的问题。 Now, you should do: 现在,您应该执行以下操作:

  • The numerals in the tuples are strings. 元组中的数字是字符串。 You need to make sure you convert them to int before you do the arithmetic operations as you mention in your description. 在执行描述中提到的算术运算之前,需要确保将它们转换为int
  • Pass output_data as an argument to a separate function that does the arithmetic functions you mentioned in your question. output_data作为参数传递给一个单独的函数,该函数执行您在问题中提到的算术函数。 This function should build your output list. 此功能应建立您的输出列表。

A few remarks on your code: 关于您的代码的几点说明:

  • You define the file handle in the main function, but do not pass it to the knapsack function. 您可以在main函数中定义文件句柄,但不要将其传递给knapsack函数。 But you reference it in the knapsack function which will not give you what you want. 但是您在背包功能中引用了该功能,该功能无法提供您想要的东西。 So you need to pass the datafile file handle as argument to your knapsack function. 因此,您需要将datafile文件的文件句柄作为参数传递给knapsack函数。 You do this by replacing this line in your main method from: 您可以通过以下方式在您的main方法中替换此行:

     knapsack() 

    to

     knapsack(datafile) 
  • list is the name of a built in type in Python. list是Python中内置类型的名称。 So it is wise not to use it as the name of a variable in your code. 因此,最好不要在代码中使用它作为变量的名称。

You should: 你应该:

  • send dataFile to your knapsack function. 发送dataFile到您的knapsack功能。
  • change from except to except IOError to avoid catching exceptions you do want to see. except改为except IOError except ,以避免捕获您确实希望看到的异常。
  • close the file (consider using with to open the file to avoid having to close it explicitly 关闭文件(考虑使用with来打开文件,以避免不得不显式关闭文件

     try: dataFile = open(fileName, "r") fileFound = True knapsack(dataFile) dataFile.close() except IOError: print ('Could not find that file -- try again') 

If you had used except IOError from the start of, you would have seen this error: 如果从一开始就使用了except IOError的东西,那么您会看到此错误:

Traceback (most recent call last):
  ...
  ...
NameError: global name 'dataFile' is not defined

knapsack does not know what dataFile is, hence the error. knapsack不知道什么是dataFile ,因此出错。 Always catch specific exceptions when using try..except . 使用try..except时,请始终捕获特定的异常。 If you don't know which error is thrown - reproduce it before you write the code in the python interpreter (eg try to open a file that doesn't exists, and notice that IOError is thrown). 如果您不知道抛出哪个错误,请在python解释器中编写代码之前重现该错误(例如,尝试打开一个不存在的文件,并注意抛出IOError )。

In knapsack you need to change from readline to readlines . knapsack您需要从readline更改为readlines

def knapsack(dataFile):
    list = dataFile.readlines()

You should also consider to use the csv module as mentioned in the other answer to handle the data. 您还应该考虑使用另一个答案中提到的csv模块来处理数据。

If I understand your question correctly, the exception is because dataFile variable is not found inside the knapsack function. 如果我正确理解了您的问题,则例外是因为在knapsack功能中找不到dataFile变量。 I'd suggest learning scoping rules in Python or read this excellent to-the-point chapter on the topic (or search for this topic on the Web!). 我建议在Python学习范围规则或阅读的话题优秀到该点章(或搜索网络上的这个话题!)。

The other thing I'd recommend is not to handle all exceptions as you've shown in your snippet. 我建议的另一件事是不处理代码段中显示的所有异常 Here's why . 这就是为什么

The fixed code could look something like this: 固定代码可能如下所示:

def main():
    fileFound = False
    while not fileFound:
        fileName = raw_input('File name containing jewel data: ')
        try:
            dataFile = open(fileName, "r")
            fileFound = True
            knapsack(dataFile)
        except IOError:
            print ('Could not find that file -- try again')

def knapsack(dataFile):
    list = dataFile.readline() ### Or you want `readlines()` ?
    print list ### Print to let you know that it works
    # return list ### ???

if __name__ == '__main__':
    main()

I would go with something more Pythonic using list comprehensions 我会使用列表推导使用更多Pythonic

def knapsack(dataFile):
    with open(dataFile, 'r') as fp:
        lines = [line.strip() for line in fp]

    data = [tuple(line.split(',')) for line in lines]

    return data

Where you are passing to your knapsack function the path to your file. 将文件传递到背包功能的位置。

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

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