Txt dosyasına bir dikte yazıp tekrar okuyor musunuz?


115

Bir txt dosyasına sözlük yazmaya çalışıyorum. Ardından tuşları ile yazarak dikte değerlerini okuyun raw_input. Sadece bir adımı kaçırdığımı hissediyorum ama bir süredir arıyordum.

Bu hatayı alıyorum

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

Kodum:

#!/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)

Bu kodla ilgili sorun nedir?
Blender

name 'p' is not defined, p, Kişi sınıfının bir örneği olmalıdır
avasal

Yanıtlar:


97

Kodunuz neredeyse doğru ! Haklısın, sadece bir adımı atlıyorsun. Dosyayı okuduğunuzda, onu bir dizge olarak okursunuz; ama dizeyi tekrar sözlüğe dönüştürmek istiyorsunuz.

Gördüğünüz hata mesajı self.whip, sözlük değil, bir dizedir.

İlk önce dizeyi besleyebileceğinizi yazdım dict()ama bu işe yaramıyor! Başka bir şey yapmalısın.

Misal

İşte en basit yol: dizeyi içine beslemek eval(). Şöyle:

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

Tek satırda yapabilirsiniz, ama bence bu şekilde dağınık görünüyor:

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

Ancak eval()bazen tavsiye edilmez. Sorun şu ki eval(), herhangi bir dizeyi değerlendirecek ve birisi sizi gerçekten zor bir dizeyi çalıştırmanız için kandırırsa, kötü bir şey olabilir. Bu durumda, sadece eval()kendi dosyanız üzerinde çalışıyorsunuz , bu yüzden sorun olmayacak.

Ancak eval()yararlı olduğu için, birisi daha güvenli bir alternatif oluşturdu. Bu denir literal_evalve onu adı verilen bir Python modülünden alırsınız ast.

import ast

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

ast.literal_eval() sadece temel Python türlerine dönüşen dizeleri değerlendirecektir, bu nedenle zor bir dizenin bilgisayarınızda kötü bir şey yapmasının hiçbir yolu yoktur.

DÜZENLE

Aslında, Python'daki en iyi uygulama with, dosyanın düzgün şekilde kapatıldığından emin olmak için bir ifade kullanmaktır . Bir withifade kullanmak için yukarıdakileri yeniden yazmak :

import ast

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

"CPython" olarak bilinen en popüler Python'da, withyerleşik "çöp toplama" özellikleri dosyayla işinizin bittiğini anlar ve sizin için kapatır çünkü genellikle ifadeye ihtiyacınız yoktur . Ancak "Jython" (Java VM için Python) veya "PyPy" (tam zamanında kod optimizasyonuna sahip gerçekten harika bir deneysel sistem) gibi diğer Python uygulamaları dosyayı sizin için kapatmayabilir. Kullanmayı alışkanlık haline withgetirmek güzel ve bence bu kodu anlamayı oldukça kolaylaştırıyor.


dict()bir sözlük veya tuple listesi bekliyor. Bir dizeyi değerlendirmez.
Blender

@Blender Oh, haklısın ve ben yorgunum. Cevabı düzenleyeceğim.
steveha

@Nick: Önce çalıştırmayı deneyin;)
Blender

@Blender, uyarı için teşekkürler. Ve yorgun olduğum için StackOverflow'da bir gece için gönderi paylaşmayı bırakacağım! :-)
steveha

175

Json modülünü denediniz mi? JSON formatı python sözlüğüne çok benzer. Ve insan tarafından okunabilir / yazılabilir:

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

Bu kod bir metin dosyasına dökülür

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

Ayrıca bir JSON dosyasından da yükleyebilirsiniz:

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

5
Daha withsonra kapanmasını sağlamak için dosyayı bir ifadede okumak / yazmak için açmanız gerekir mi ?
ecoe

2
WOW, bu çok güzel.
zx1986

3
İç içe geçmiş set değerlerine sahip bazı karmaşık sözlüklerde bu yöntemi kullanırken sorunlar yaşadım (örn. d = {"one": {"1" : 1, "a": {"i"}}}). Bu nedenle, @ blender'ın benim durumumda çalışan turşu yöntemini öneriyorum.
Gürol Canbek

1
Python'un json'unun json.dump yaparken dict anahtarlarını dizelere çevirdiğine dikkat edin, bu yüzden json.load yaparken json.dump({1: 'one'}, file)olduğu gibi {'1': 'one'}okuyacaktır. Kaydedilen dosyayı Python dışındaki dilleri kullanarak okumayacaksanız turşu kullanmak daha iyidir.
peeol

Diktenin dosyaya yazılma şeklini daha okunaklı hale getirmek için biçimlendirmek için json.dumps (dict_x, indent = 4) gibi bir şey kullanmanın bir yolu var mı? Kodunuzu kullandığımda, tüm diktenin büyüklüğü ne kadar büyük olursa olsun tek satıra yazılır ve okunması kolay değildir.
herteladrian

70

Python nesnelerini dosyalarda saklamak için şu picklemodülü kullanın :

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

Hiçbir zaman ayarlamadığıma b = a, bunun yerine abir dosyaya koyduğuma ve sonra onu açtığıma dikkat edin b.

Senin hatana gelince:

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

self.whipbir sözlük nesnesiydi. deed.txtmetni içerir, bu nedenle içeriğini yüklediğinizde deed.txtiçine self.whip, self.whipolur dize kendisinin temsili.

Muhtemelen dizeyi tekrar bir Python nesnesi olarak değerlendirmek istersiniz:

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

Nasıl evalgöründüğüne dikkat edin evil. Bu kasıtlı. Kullanım pickleyerine modülü.


hayır bana bu hatayı veriyor Dosya "name.py", satır 24, print whip [name] okunurken TypeError: string indeksleri tamsayı olmalı, str diye düşünmemiştim p = Person () onu tanımladı
Radioactive Head

Bu metin kodunuzda yok. Bir soru sormadan önce sorunun ne olduğunu açıklayın.
Blender

2
Python nesnelerini dosyalarda saklamak için turşu modülünü kullanın Bunlar yapılandırma dosyaları olmadıkça, bu nedenle onların insan tarafından düzenlenebilir olmasını istiyorsanız - bkz. Python ve yapılandırma dosyalarıyla neden uğraşasınız?
Piotr Dobrogost

1
Mükemmel. Tam olarak ihtiyacım olan şey bu: yerel python yapı durumunu kullanıcı tarafından düzenlenebilir olması amaçlanmayan bir dosyada depolamak.
bahamat

Bu yöntem, @KFL tarafından önerilen JSON yöntemi için yaptığım yorumda anlattığım gibi karmaşık sözlükler için mükemmel çalışıyor
Gürol Canbek

8

Gerçekten güzel çalışan kendi işlevlerimi yarattım:

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

Önce anahtar adını, ardından tüm değerleri saklar. Bu durumda diktemin tamsayılar içerdiğine dikkat edin, bu yüzden int. Bu, büyük olasılıkla durumunuz için değiştirmeniz gereken kısımdır.

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)

Değerleriniz çok uzun değilse harika kod.
Anne

7

Merhaba, sözlüğü dosyaya yazmanın ve okumanın bir yolu var, sözlüğünüzü JSON formatına çevirebilir ve hızlıca okuyup yazabilirsiniz, sadece şunu yapın:

için yazmak tarihinizi:

 import json

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

ve verilerinizi okumak için:

 import json

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

6

Anahtar / değer çiftini yineleyebilir ve bunu dosyaya yazabilirsiniz

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')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.