Ein Diktat in eine TXT-Datei schreiben und zurücklesen?

115

Ich versuche, ein Wörterbuch in eine txt-Datei zu schreiben. Lesen Sie dann die Diktatwerte, indem Sie die Tasten mit eingeben raw_input. Ich habe das Gefühl, dass mir nur ein Schritt fehlt, aber ich habe jetzt schon eine Weile gesucht.

Ich bekomme diesen Fehler

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

Mein Code:

#!/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)
Radioaktiver Kopf
quelle
Was ist das Problem mit diesem Code?
Blender
name 'p' is not defined, p sollte eine Instanz der Personenklasse sein
avasal

Antworten:

97

Ihr Code ist fast richtig ! Sie haben Recht, Sie verpassen nur einen Schritt. Wenn Sie die Datei einlesen, lesen Sie sie als Zeichenfolge. Sie möchten die Zeichenfolge jedoch wieder in ein Wörterbuch umwandeln.

Die Fehlermeldung, die Sie gesehen haben, war, weil self.whipes sich um eine Zeichenfolge und nicht um ein Wörterbuch handelte.

Ich habe zuerst geschrieben, dass man den String einfach einspeisen kann, dict()aber das funktioniert nicht! Sie müssen etwas anderes tun.

Beispiel

Hier ist der einfachste Weg: Führen Sie den String ein eval(). Wie so:

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

Sie können es in einer Zeile tun, aber ich denke, es sieht auf diese Weise chaotisch aus:

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

Wird eval()aber manchmal nicht empfohlen. Das Problem ist, dass jede Zeichenfolge eval()ausgewertet wird. Wenn Sie jemand dazu verleitet hat, eine wirklich schwierige Zeichenfolge auszuführen, kann etwas Schlimmes passieren. In diesem Fall führen Sie nur Ihre eigene Datei aus, daher sollte dies in Ordnung sein.eval()

Aber weil eval()es nützlich ist, hat jemand eine Alternative dazu gemacht, die sicherer ist. Dies wird aufgerufen literal_evalund Sie erhalten es von einem Python-Modul namens ast.

import ast

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

ast.literal_eval() Es werden nur Zeichenfolgen ausgewertet, die sich in die grundlegenden Python-Typen verwandeln. Es gibt also keine Möglichkeit, dass eine knifflige Zeichenfolge auf Ihrem Computer etwas Schlechtes bewirken kann.

BEARBEITEN

In Python empfiehlt es sich, eine withAnweisung zu verwenden, um sicherzustellen, dass die Datei ordnungsgemäß geschlossen wird. Schreiben Sie das Obige neu, um eine withAnweisung zu verwenden:

import ast

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

Im beliebtesten Python, bekannt als "CPython", benötigen Sie die withAnweisung normalerweise nicht , da die integrierten Funktionen "Garbage Collection" feststellen, dass Sie mit der Datei fertig sind, und sie für Sie schließen. Andere Python-Implementierungen wie "Jython" (Python für die Java-VM) oder "PyPy" (ein wirklich cooles experimentelles System mit Just-in-Time-Code-Optimierung) können die Datei möglicherweise nicht für Sie schließen. Es ist gut, sich daran zu gewöhnen with, und ich denke, es macht den Code ziemlich einfach zu verstehen.

steveha
quelle
dict()erwartet ein Wörterbuch oder eine Liste von Tupeln. Es wird keine Zeichenfolge ausgewertet.
Blender
@Blender Oh, du hast recht und ich bin müde. Ich werde die Antwort bearbeiten.
Steveha
@ Nick: Versuchen Sie es zuerst auszuführen;)
Blender
@Blender, danke für das Heads-up. Und da ich müde bin, denke ich, dass ich für die Nacht aufhören werde, auf StackOverflow zu posten! :-)
Steveha
173

Haben Sie das JSON-Modul ausprobiert ? Das JSON-Format ist dem Python-Wörterbuch sehr ähnlich. Und es ist menschlich lesbar / beschreibbar:

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

Dieser Code wird in eine Textdatei geschrieben

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

Sie können auch aus einer JSON-Datei laden:

>>> d2 = json.load(open("text.txt"))
>>> print d2
{u'two': 2, u'one': 1}
KFL
quelle
5
Sollten Sie die Datei zum Lesen / Schreiben in einer withAnweisung öffnen, um sicherzustellen, dass sie danach geschlossen wird?
Öko
2
WOW, das ist so schön.
zx1986
3
Ich hatte Probleme bei der Verwendung dieser Methode in einigen komplexen Wörterbüchern, z d = {"one": {"1" : 1, "a": {"i"}}}. B. mit verschachtelten Sollwerten (z . B. ). Daher empfehle ich die Pickle-Methode von @ blender, die in meinem Fall funktioniert.
Gürol Canbek
1
Beachten Sie, dass json von Python Diktatschlüssel in Zeichenfolgen übersetzt, wenn Sie json.dump ausführen. Dies wird also json.dump({1: 'one'}, file)wie {'1': 'one'}bei json.load zurückgelesen. Verwenden Sie Pickle besser, wenn Sie die gespeicherte Datei nicht in anderen Sprachen als Python lesen möchten.
Peeol
Gibt es eine Möglichkeit, etwas wie json.dumps (dict_x, indent = 4) zu verwenden, um die Art und Weise zu formatieren, wie das Diktat in die Datei geschrieben wird, um sie besser lesbar zu machen? Wenn ich Ihren Code verwende, wird das gesamte Diktat in eine Zeile geschrieben, egal wie groß es ist, und es ist nicht leicht von Menschen lesbar.
Herteladrian
69

Verwenden Sie das pickleModul, um Python-Objekte in Dateien zu speichern :

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

Beachten Sie, dass ich nie eine Datei festgelegt b = a, sondern ain eine Datei eingelegt und sie dann aufgehoben habe b.

Wie für Ihren Fehler:

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

self.whipwar ein Wörterbuchobjekt. deed.txtEnthält Text. Wenn Sie also den Inhalt von deed.txtin laden self.whip, self.whipwird dies zur Zeichenfolgendarstellung von sich selbst.

Sie möchten den String wahrscheinlich wieder in ein Python-Objekt auswerten:

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

Beachten Sie, wie sich das evalanhört evil. Das ist beabsichtigt. Verwenden Sie picklestattdessen das Modul.

Mixer
quelle
Nein, es gibt mir diesen Fehler. Datei "name.py", Zeile 24, beim Lesen von print whip [name] TypeError: Zeichenfolgenindizes müssen Ganzzahlen sein, nicht str. Ich dachte, p = Person () hat sie definiert
Radioactive Head
Dieser Text ist nicht in Ihrem Code enthalten. Erklären Sie, was falsch ist, bevor Sie eine Frage stellen.
Blender
2
Verwenden Sie zum Speichern von Python-Objekten in Dateien das Pickle-Modul. Sofern es sich nicht um Konfigurationsdateien handelt, möchten Sie, dass diese von Menschen bearbeitet werden können - siehe Warum sich mit Python- und Konfigurationsdateien beschäftigen?
Piotr Dobrogost
1
Perfekt. Dies ist genau das, was ich brauche: um den nativen Python-Strukturstatus in einer Datei zu speichern, die nicht vom Benutzer bearbeitet werden kann.
Bahamat
Diese Methode funktioniert perfekt für komplexe Wörterbücher, wie ich in meinem Kommentar für die von @KFL
Gürol Canbek am
8

Ich habe meine eigenen Funktionen erstellt, die wirklich gut funktionieren:

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

Der Keyname wird zuerst gespeichert, gefolgt von allen Werten. Beachten Sie, dass mein Diktat in diesem Fall Ganzzahlen enthält, weshalb es in konvertiert wird int. Dies ist höchstwahrscheinlich der Teil, den Sie für Ihre Situation ändern müssen.

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)
PascalVKooten
quelle
Toller Code, wenn Ihre Werte nicht zu lang sind. Mein Wörterbuch enthielt mehrere lange Zeichenfolgen, die gerade mit '...' abgeschnitten wurden
Anne
7

Hallo, es gibt eine Möglichkeit, das Wörterbuch in eine Datei zu schreiben und zu lesen. Sie können Ihr Wörterbuch in das JSON-Format umwandeln und schnell lesen und schreiben.

So schreiben Sie Ihr Datum:

 import json

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

und um Ihre Daten zu lesen :

 import json

 f = open('destFile.txt', 'r')
 your_dictionary = json.loads(f.read())
Manouchehr Rasouli
quelle
6

Sie können das Schlüssel-Wert-Paar durchlaufen und in eine Datei schreiben

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')
Aravind Krishnakumar
quelle