จะบันทึกพจนานุกรมลงในไฟล์ได้อย่างไร?


149

ฉันมีปัญหากับการเปลี่ยนค่า dict และบันทึก dict เป็นไฟล์ข้อความ (รูปแบบต้องเหมือนกัน) ฉันต้องการเปลี่ยนmember_phoneฟิลด์เท่านั้น

ไฟล์ข้อความของฉันอยู่ในรูปแบบต่อไปนี้:

memberID:member_name:member_email:member_phone

และฉันแยกไฟล์ข้อความด้วย:

mdict={}
for line in file:
    x=line.split(':')
    a=x[0]
    b=x[1]
    c=x[2]
    d=x[3]
    e=b+':'+c+':'+d

    mdict[a]=e

เมื่อฉันลองเปลี่ยนที่member_phoneเก็บไว้dค่าไม่ได้เปลี่ยนไปตามคีย์

def change(mdict,b,c,d,e):
    a=input('ID')
    if a in mdict:
        d= str(input('phone'))
        mdict[a]=b+':'+c+':'+d
    else:
        print('not')

และจะบันทึกคำสั่งลงในไฟล์ข้อความที่มีรูปแบบเดียวกันได้อย่างไร

คำตอบ:


277

Python มีโมดูลดองสำหรับสิ่งนี้เท่านั้น

ฟังก์ชั่นเหล่านี้เป็นสิ่งที่คุณต้องการสำหรับการบันทึกและโหลดเกือบทุกวัตถุ:

def save_obj(obj, name ):
    with open('obj/'+ name + '.pkl', 'wb') as f:
        pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)

def load_obj(name ):
    with open('obj/' + name + '.pkl', 'rb') as f:
        return pickle.load(f)

ฟังก์ชันเหล่านี้สมมติว่าคุณมีobjโฟลเดอร์ในไดเร็กทอรีการทำงานปัจจุบันของคุณซึ่งจะใช้ในการจัดเก็บอ็อบเจ็กต์

โปรดทราบว่าpickle.HIGHEST_PROTOCOLเป็นรูปแบบไบนารีซึ่งอาจไม่สะดวกเสมอไป แต่ดีต่อประสิทธิภาพ โปรโตคอล0คือรูปแบบข้อความ

ในการบันทึกคอลเลกชันของ Python มีโมดูลชั้นวาง


1
save_objดูเหมือนว่าจะต้องมีไฟล์obj/'+ name + '.pklอยู่แล้ว ฉันสร้างพจนานุกรมชื่อQเติมข้อมูลและโทรออกว่าsave_obj(Q, "Qtable")ฉันได้รับข้อผิดพลาด: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'จะสร้างไฟล์ได้อย่างไรในตอนแรกก่อนที่จะเขียนมัน?
ดอกไม้ทะเลไม้จิ้มฟัน

1
@ToothpickAnemone ใช้wb+ในการสร้างไฟล์คือ:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s

2
@ andrey.s: ฉันไม่คิดว่าสิ่งที่คุณพูดจะสร้างความแตกต่างเพราะมันไม่ได้ช่วยแก้ปัญหา
martineau

3
@Toothpick Anemone: การเพิ่ม a +ลงในโหมดจะไม่มีผลกับปัญหาของคุณ (andrey.s ไม่ถูกต้อง) ปัญหาของคุณดูเหมือนจะเป็นเพราะหนึ่งหรือสองสิ่ง เพื่อให้save_obj()คำตอบนี้ใช้งานได้ไดเร็กทอรีย่อยที่ชื่อ"obj"ต้องมีอยู่แล้วเนื่องจากopen()จะไม่สร้างขึ้นโดยอัตโนมัติ ประการที่สองอาร์กิวเมนต์แรกsave_obj()คือวัตถุ Python ที่จะบันทึกไม่ใช่ชื่อของไดเร็กทอรีย่อย (แม้ว่าจะไม่ชัดเจนว่าคุณหมายถึงอะไรQในการsave_obj(Q, "Qtable")เรียกในตัวอย่างก็ตาม) os.mkdir()คุณสามารถสร้างไดเรกทอรีถ้ามันไม่ได้แล้วออกมาด้วย
martineau

176

Pickle น่าจะเป็นตัวเลือกที่ดีที่สุด แต่ในกรณีที่ใคร ๆ สงสัยว่าจะบันทึกและโหลดพจนานุกรมลงในไฟล์โดยใช้ NumPy ได้อย่างไร:

import numpy as np

# Save
dictionary = {'hello':'world'}
np.save('my_file.npy', dictionary) 

# Load
read_dictionary = np.load('my_file.npy',allow_pickle='TRUE').item()
print(read_dictionary['hello']) # displays "world"

FYI: โปรแกรมดูไฟล์ NPY


4
. item () สำหรับอะไร?
Gulzar

เหตุใดคำตอบนี้จึงได้รับการโหวตน้อยกว่าคำตอบ "ดอง" ของ @Zah พื้นที่ซับซ้อนมากขึ้น?
Nathan

1
@frank เป็นไปได้เพราะดองเป็นส่วนหนึ่งของไลบรารีมาตรฐานของ python โดยที่ numpy เป็นโครงการอิสระ
Maxim Veksler

2
@Gulzar จากสิ่งที่ฉันค้นหา np.load ส่งคืน ndarray (ทำการtype(read_dictionary)เปิดเผย) และ. item () โดยทั่วไปจะแปลงองค์ประกอบนั้นเป็นวัตถุ python สเกลาร์ซึ่งเป็นพจนานุกรมตามที่ระบุไว้ที่นี่
abhyudayasrinet

2
@ คุณชัยได้ติดตั้งแพ็คเกจ numpy ... ?
Eben

32

นอกจากนี้เรายังสามารถใช้jsonโมดูลนี้ในกรณีที่พจนานุกรมหรือข้อมูลอื่น ๆ สามารถแมปกับรูปแบบJSONได้อย่างง่ายดาย

import json

# Serialize data into file:
json.dump( data, open( "file_name.json", 'w' ) )

# Read data from file:
data = json.load( open( "file_name.json" ) )

วิธีนี้นำประโยชน์มากมายเช่นงานสำหรับหลาม 2.xและงูหลาม 3.xในรูปแบบที่ไม่เปลี่ยนแปลงและนอกจากนี้ข้อมูลที่บันทึกไว้ในJSONรูปแบบสามารถโอนได้อย่างง่ายดายระหว่างแพลตฟอร์มที่แตกต่างกันหรือโปรแกรม ข้อมูลนี้นอกจากนี้ยังมีมนุษย์สามารถอ่านได้


1
วิธีการที่ดี แต่ผมไม่คิดว่ามันปลอดภัยที่จะใช้โดยตรงแทนบริบทที่สร้างขึ้นโดยopen withมีการรับประกันไหมที่จับไฟล์จะปิดถ้าjson.dumpล้มเหลว?
Dr_Zaszuś

18

ฉันไม่แน่ใจว่าคำถามแรกของคุณคืออะไร แต่ถ้าคุณต้องการบันทึกพจนานุกรมเป็นไฟล์คุณควรใช้jsonไลบรารี ค้นหาเอกสารของโหลดและวางฟังก์ชัน


ทำไมต้อง json? มันง่ายกว่าที่จะถ่ายโอนพจนานุกรม Python ไปยังไฟล์โดยใช้ "repr"
mguijarr

5
@mguijarr แต่การแยกวิเคราะห์กลับไม่ใช่เรื่องง่าย Plus json นั้นง่ายต่อการแก้ไขด้วยมือและนำเข้าสู่โปรแกรมอื่น ๆ
kalhartt

1
ฉันชอบคำแนะนำของ John - ดูโพสต์นี้สำหรับตัวอย่างที่ดีและเรียบง่ายstackoverflow.com/a/11027021/765827
jacanterbury


9

ฉันขอแนะนำให้บันทึกข้อมูลของคุณโดยใช้รูปแบบ JSON แทนรูปแบบการดองเนื่องจากไฟล์ของ JSON สามารถอ่านได้โดยมนุษย์ซึ่งทำให้การดีบักของคุณง่ายขึ้นเนื่องจากข้อมูลของคุณมีขนาดเล็ก ไฟล์ JSON ยังใช้โดยโปรแกรมอื่นเพื่ออ่านและเขียนข้อมูล คุณสามารถอ่านเพิ่มเติมได้ที่นี่

คุณจะต้องติดตั้งโมดูล JSON คุณสามารถทำได้ด้วย pip:

pip install json


# To save the dictionary into a file:
json.dump( data, open( "myfile.json", 'w' ) )

สิ่งนี้สร้างไฟล์ json ที่มีชื่อ myfile

# To read data from file:
data = json.load( open( "myfile.json" ) )

สิ่งนี้อ่านและจัดเก็บข้อมูล myfile.json ในออบเจ็กต์ข้อมูล


3

สำหรับพจนานุกรมของสตริงเช่นที่คุณกำลังจัดการอยู่สามารถทำได้โดยใช้ความสามารถในการประมวลผลข้อความในตัวของ Python เท่านั้น

(โปรดทราบว่าจะใช้ไม่ได้หากค่าเป็นอย่างอื่น)

with open('members.txt') as file:
    mdict={}
    for line in file:
        a, b, c, d = line.strip().split(':')
        mdict[a] = b + ':' + c + ':' + d

a = input('ID: ')
if a not in mdict:
    print('ID {} not found'.format(a))
else:
    b, c, d = mdict[a].split(':')
    d = input('phone: ')
    mdict[a] = b + ':' + c + ':' + d  # update entry
    with open('members.txt', 'w') as file:  # rewrite file
        for id, values in mdict.items():
            file.write(':'.join([id] + values.split(':')) + '\n')

สิ่งนี้ใช้ไม่ได้กับพจนานุกรม: file.write (':'. join ([id] + values.split (':')) + '\ n') AttributeError: วัตถุ 'dict' ไม่มีแอตทริบิวต์ 'split'
Shai Alon

@ShaiAlon: ไม่ใช่กับพวกเขาทั้งหมดไม่ใช่ แน่นอนมันไม่ทำงานกับคนที่มีค่าเป็นสตริง (ที่มีsplit()วิธีการ) -which เป็นหัวข้อของคำถามนี้ ดูเหมือนว่าคุณกำลังพยายามใช้มันในพจนานุกรมของพจนานุกรมดังนั้นจึงไม่สามารถใช้กับพจนานุกรมเหล่านั้นได้ ฉันไม่ชอบการโหวตจากคนอื่น ๆ เพราะพวกเขาไม่เข้าใจคำถามจริงๆ (และบริบทของคำตอบที่ให้ไว้) ฉันจะอัปเดตคำตอบของฉันเพื่อให้เมื่อใช้มันจะเหมาะสมดังนั้นโปรดยกเลิกการลงคะแนนของคุณ
martineau

2

ถ้าคุณไม่ต้องการเก็บพจนานุกรมไว้จริงๆฉันคิดว่าทางออกที่ดีที่สุดคือใช้csvโมดูล Python เพื่ออ่านไฟล์ จากนั้นคุณจะได้รับแถวข้อมูลและคุณสามารถเปลี่ยนแปลงmember_phoneหรืออะไรก็ได้ที่คุณต้องการ สุดท้ายคุณสามารถใช้csvโมดูลอีกครั้งเพื่อบันทึกไฟล์ในรูปแบบเดียวกับที่คุณเปิด

รหัสสำหรับการอ่าน:

import csv

with open("my_input_file.txt", "r") as f:
   reader = csv.reader(f, delimiter=":")
   lines = list(reader)

รหัสสำหรับการเขียน:

with open("my_output_file.txt", "w") as f:
   writer = csv.writer(f, delimiter=":")
   writer.writerows(lines)

แน่นอนคุณต้องปรับchange()ฟังก์ชันของคุณ:

def change(lines):
    a = input('ID')
    for line in lines:
      if line[0] == a:
        d=str(input("phone"))
        line[3]=d
        break
    else:
      print "not"

หมายความว่าอย่างไรOf course, you need to adapt your change() function:
kRazzy R

1
ในคำถาม a dict ถูกใช้ในขณะที่ csv ทำงานเหมือนรายการมากกว่า
mguijarr

1

ฉันยังไม่หมดเวลา แต่ฉันพนันได้เลยว่า h5 เร็วกว่าของดอง ขนาดไฟล์ที่บีบอัดจะเล็กกว่า

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))

0

เนื่องจาก Pickle มีข้อกังวลด้านความปลอดภัยและทำงานช้า (ที่มา ) ฉันจะไปหา JSON เพราะมันเร็วในตัวมนุษย์อ่านได้และใช้แทนกันได้:

import json
data = {'another_dict': {'a': 0, 'b': 1}, a_list: [0, 1, 2, 3]}
# e.g. file = './data.json' 
with open(file, 'w') as f: 
    json.dump(datastore, f)

การอ่านง่ายเหมือนกัน:

with open(file, 'r') as f:
    data = json.load(f)

คล้ายกับคำตอบนี้แต่ใช้การจัดการไฟล์อย่างถูกต้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.