dictを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年

回答:


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)

「CPython」として知られている最も人気のあるPythonではwith、組み込みの「ガベージコレクション」機能によってファイルの処理が完了し、ファイルが閉じられるため、通常はステートメントは必要ありません。しかし、「Jython」(Java VMのPython)や「PyPy」(ジャストインタイムのコード最適化を備えた非常に優れた実験的なシステム)などの他のPython実装は、ファイルを閉じる方法を理解できない場合があります。を使用する習慣を身に付けるのは良いwithことです。コードを理解するのはかなり簡単になると思います。


dict()辞書またはタプルのリストが必要です。文字列を評価しません。
Blender 2012年

@ブレンダーああ、あなたは正しいと私は疲れています。答えを編集します。
steveha

@ニック:まず実行してみてください;)
Blender

@ブレンダー、ヘッズアップありがとうございます。そして私は疲れているので、一晩StackOverflowに投稿するのをやめると思います!:-)
steveha

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 '29

3
ネストされた設定値(などd = {"one": {"1" : 1, "a": {"i"}}})を持つようないくつかの複雑な辞書でこの方法を使用するときに問題が発生しました。したがって、私は私の場合に機能する@blenderのpickleメソッドをお勧めします。
GürolCanbek

1
Pythonのjsonは、json.dumpを実行するときにdictキーを文字列に変換するため、json.loadを実行json.dump({1: 'one'}, file)する{'1': 'one'}場合と同じように読み返されることに注意してください。Python以外の言語を使用して保存したファイルを読み取らない場合は、ピクルを使用することをお勧めします。
peeol 2017年

json.dumps(dict_x、indent = 4)のようなものを使用して、ファイルを読みやすくするためにファイルにdictを書き込む方法をフォーマットする方法はありますか?私があなたのコードを使用するとき、dict全体が1行に書き込まれます。それがどんなに大きくても、それは簡単に人間が読むことはできません。
herteladrian、2017年

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ファイルにpickle 化してからunpickleしてb

あなたのエラーについては:

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

self.whip辞書オブジェクトでした。deed.txtテキストが含まれているので、あなたが内容をロードする際deed.txtself.whipself.whipなり文字列そのものの表現。

おそらく、文字列を評価してPythonオブジェクトに戻したいでしょう。

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

どのようにeval聞こえるかに注意してくださいevil。それは意図的です。pickle代わりにモジュールを使用してください。


いいえ、それは私にこのエラーを与えます印刷whip [name] TypeErrorを読み取る際のファイル "name.py"、24行目TypeError:文字列インデックスは整数である必要がありますstrではありませんp = Person()がそれを定義しました
Radioactive Head

そのテキストはコードに含まれていません。質問する前に、何が悪いのか説明してください。
Blender 2012年

2
Pythonオブジェクトをファイルに保存するには、pickleモジュールを使用します。これらが設定ファイルでない限り、それらを人間が編集できるようにする必要があります。Pythonと設定ファイルに煩わされる理由を
Piotr Dobrogost

1
完璧です。これはまさに私が必要とするものです:ユーザーが編集できるように意図されていないファイルにネイティブのPython構造の状態を保存するため。
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

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())

6

キーと値のペアを反復処理してファイルに書き込むことができます

pair = {'name': name,'location': location}
with open('F:\\twitter.json', 'a') as f:
     f.writelines('{}:{}'.format(k,v) for k, v in pair.items())
     f.write('\n')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.