写一个字典到txt文件并读回去?


115

我正在尝试将字典写入txt文件。然后使用键入键以读取dict值raw_input。我觉得我只差一步,但现在已经找了一段时间。

我得到这个错误

File "name.py", line 24, in reading
    print whip[name]
TypeError: string indices must be integers, not str

我的代码:

#!/usr/bin/env python
from sys import exit

class Person(object):
    def __init__(self):
        self.name = ""
        self.address = ""
        self.phone = ""
        self.age = ""
        self.whip = {}

    def writing(self):
        self.whip[p.name] = p.age, p.address, p.phone
        target = open('deed.txt', 'a')
        target.write(str(self.whip))
        print self.whip

    def reading(self):
        self.whip = open('deed.txt', 'r').read()
        name = raw_input("> ")
        if name in self.whip:
            print self.whip[name]

p = Person()

while True:
    print "Type:\n\t*read to read data base\n\t*write to write to data base\n\t*exit to exit"
    action = raw_input("\n> ")
    if "write" in action:
        p.name = raw_input("Name?\n> ")
        p.phone = raw_input("Phone Number?\n> ")
        p.age = raw_input("Age?\n> ")
        p.address = raw_input("Address?\n>")
        p.writing()
    elif "read" in action:
        p.reading()
    elif "exit" in action:
        exit(0)

这段代码有什么问题?
Blender 2012年

name 'p' is not defined,p应该是Person类的实例
Avasal 2012年

Answers:


97

您的代码几乎正确!没错,您只差一步。当您读入文件时,您将以字符串形式读取它;但是您想将字符串转换成字典。

您看到的错误消息是因为self.whip是字符串,而不是字典。

我首先写道,您可以只将字符串输入其中,dict()但这不起作用!您需要做其他事情。

这是最简单的方法:将字符串输入eval()。像这样:

def reading(self):
    s = open('deed.txt', 'r').read()
    self.whip = eval(s)

您可以一行完成它,但是我认为这种方式看起来很混乱:

def reading(self):
    self.whip = eval(open('deed.txt', 'r').read())

但是eval()有时不推荐。问题是,eval()它将评估任何字符串,如果有人欺骗您运行了真正棘手的字符串,则可能会发生不良情况。在这种情况下,您只是eval()在自己的文件上运行,因此应该可以。

但是因为eval()有用,所以有人替代了它,使其更安全。这被称为literal_eval,您可以从名为的Python模块中获取该代码ast

import ast

def reading(self):
    s = open('deed.txt', 'r').read()
    self.whip = ast.literal_eval(s)

ast.literal_eval() 只会评估转换为基本Python类型的字符串,因此,棘手的字符串无法对您的计算机造成不良影响。

编辑

实际上,Python中的最佳实践是使用with语句来确保正确关闭文件。重写以上内容以使用以下with语句:

import ast

def reading(self):
    with open('deed.txt', 'r') as f:
        s = f.read()
        self.whip = ast.literal_eval(s)

在最流行的Python(称为“ CPython”)中,您通常不需要该with语句,因为内置的“垃圾收集”功能将确定您已完成文件并会为您关闭文件。但是其他Python实现,例如“ Jython”(用于Java VM的Python)或“ PyPy”(具有即时代码优化的非常酷的实验系统)可能无法为您关闭文件。养成使用的习惯是很好的with,而且我认为这使代码非常容易理解。


dict()需要字典或元组列表。它不会评估字符串。
Blender 2012年

@Blender哦,你是对的,我很累。我将编辑答案。
steveha 2012年

@Nick:尝试先运行它;)
Blender

@Blender,谢谢您的注意。而且由于我很累,我想我将在晚上停止在StackOverflow上发帖!:-)
steveha 2012年

175

您是否尝试过json模块?JSON格式与python字典非常相似。它是人类可读/可写的:

>>> import json
>>> d = {"one":1, "two":2}
>>> json.dump(d, open("text.txt",'w'))

此代码转储到文本文件

$ cat text.txt 
{"two": 2, "one": 1}

您也可以从JSON文件加载:

>>> d2 = json.load(open("text.txt"))
>>> print d2
{u'two': 2, u'one': 1}

5
您是否应该在with语句中打开文件以进行读/写操作以确保之后关闭?
ecoe 2014年

2
哇,真漂亮。
zx1986

3
在某些复杂的字典上使用此方法时遇到了问题,例如具有嵌套的设置值(例如d = {"one": {"1" : 1, "a": {"i"}}})。因此,我建议在我的情况下可以使用@blender的pickle方法。
GürolCanbek

1
请注意,在执行json.dump时,python的json将dict键转换为字符串,因此在执行json.load时json.dump({1: 'one'}, file)将读回{'1': 'one'}。如果您不打算使用Python以外的其他语言读取保存的文件,则最好使用pickle。
peeol

有没有办法使用json.dumps(dict_x,indent = 4)之类的格式将dict写入文件的方式使其更清晰?当我使用您的代码时,无论字典多大,整个字典都被写到一行,而且它也不容易被人阅读。
herteladrian

70

要将Python对象存储在文件中,请使用以下pickle模块:

import pickle

a = {
  'a': 1,
  'b': 2
}

with open('file.txt', 'wb') as handle:
  pickle.dump(a, handle)

with open('file.txt', 'rb') as handle:
  b = pickle.loads(handle.read())

print a == b # True

请注意,我从未设置b = a,而是a将其腌制到一个文件中,然后将其解开b

至于你的错误:

self.whip = open('deed.txt', 'r').read()

self.whip是一个字典对象。deed.txt包含文本,因此当您将的内容加载deed.txt到中时self.whip,它便self.whip成为其自身的字符串表示形式。

您可能希望将字符串求值返回给Python对象:

self.whip = eval(open('deed.txt', 'r').read())

注意eval听起来如何evil。那是故意的。请改用pickle模块。


不,它给我这个错误文件“ name.py”,第24行,在读取打印whip [name]时出现TypeError:字符串索引必须是整数,而不是str我认为p = Person()定义了它
放射性头

该文本不在您的代码中。提出问题之前,请先说明问题所在。
Blender 2012年

2
要将Python对象存储在文件中,请使用pickle模块,除非这些是配置文件,否则您希望它们可以被人类编辑-请参见为什么要打扰python和config文件?
Piotr Dobrogost

1
完善。这正是我所需要的:将本机python结构状态存储在一个不希望用户编辑的文件中。
bahamat 2013年

这种方法完全适用于我在为JSON方法注释中描述复杂的字典建议由@KFL
GürolCanbek

8

我创建了自己的函数,这些函数非常好用:

def writeDict(dict, filename, sep):
    with open(filename, "a") as f:
        for i in dict.keys():            
            f.write(i + " " + sep.join([str(x) for x in dict[i]]) + "\n")

它将首先存储键名,然后存储所有值。请注意,在这种情况下,我的字典包含整数,因此将其转换为int。这很可能是您需要根据情况更改的部分。

def readDict(filename, sep):
    with open(filename, "r") as f:
        dict = {}
        for line in f:
            values = line.split(sep)
            dict[values[0]] = {int(x) for x in values[1:len(values)]}
        return(dict)

如果您的值不太长,则代码很棒。我的字典中包含多个长字符串,这些长字符串刚被'...'切断
Anne Anne

7

嗨,有一种方法可以读写字典到文件,您可以将字典转换为JSON格式并快速读写,只需执行以下操作:

为了你的约会:

 import json

 your_dictionary = {"some_date" : "date"}
 f = open('destFile.txt', 'w+')
 f.write(json.dumps(your_dictionary))

读取您的数据:

 import json

 f = open('destFile.txt', 'r')
 your_dictionary = json.loads(f.read())

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.