Bagaimana cara menyimpan dan mengembalikan banyak variabel di python?

105

Saya perlu menyimpan sekitar selusin objek ke sebuah file dan kemudian memulihkannya nanti. Saya sudah mencoba menggunakan for loop dengan acar dan rak tetapi tidak berhasil.

Edit.
Semua objek yang saya coba simpan berada di kelas yang sama (saya seharusnya menyebutkan ini sebelumnya), dan saya tidak menyadari bahwa saya bisa menyelamatkan seluruh kelas seperti ini:

import pickle
def saveLoad(opt):
    global calc
    if opt == "save":
        f = file(filename, 'wb')
        pickle.dump(calc, f, 2)
        f.close
        print 'data saved'
    elif opt == "load":
        f = file(filename, 'rb')
        calc = pickle.load(f)
    else:
        print 'Invalid saveLoad option'
lunarfyre
sumber
1
Anda bilang Anda sudah mencoba for loop. Harap posting kode itu, dan mengapa "tidak bekerja dengan benar" (yaitu, apa yang terjadi dan apa yang Anda inginkan terjadi).
Blair
Jika Anda menggunakan windows, pastikan untuk membuka file dalam mode biner
John La Rooy
@gnibbler: mode biner hanya diperlukan untuk protokol non-default ( docs.python.org/library/pickle.html#usage ).
Eric O Lebigot

Jawaban:

170

Jika Anda perlu menyimpan banyak objek, Anda cukup memasukkannya ke dalam satu daftar, atau tuple, misalnya:

import pickle

# obj0, obj1, obj2 are created here...

# Saving the objects:
with open('objs.pkl', 'w') as f:  # Python 3: open(..., 'wb')
    pickle.dump([obj0, obj1, obj2], f)

# Getting back the objects:
with open('objs.pkl') as f:  # Python 3: open(..., 'rb')
    obj0, obj1, obj2 = pickle.load(f)

Jika Anda memiliki banyak data, Anda dapat mengurangi ukuran file dengan meneruskan protocol=-1ke dump(); picklekemudian akan menggunakan protokol terbaik yang tersedia alih-alih protokol historis default (dan lebih kompatibel ke belakang). Dalam hal ini, file harus dibuka dalam mode biner ( wbdan rb, masing-masing).

Mode biner juga harus digunakan dengan Python 3, karena protokol defaultnya menghasilkan data biner (yaitu non-teks) (mode penulisan 'wb'dan mode membaca 'rb').

Eric O Lebigot
sumber
12
Di Python 3.5, saya harus membuka file dalam mode "byte", misalnya with open('objs.pickle', 'wb') as f:(perhatikan wb).
kbrose
Hai @Eric, apa perlunya with open('objs.pkl') as f:membandingkan dengan sederhana obj1, obj2 = pickle.load(open("objs.pkl","rb"))? Apakah ada perbedaan antara keduanya?
balandongiv
Dengan bentuk kedua Anda tidak menutup file. Ini bukan praktik yang baik, karena jumlah file yang dapat Anda buka secara paralel biasanya sangat dibatasi oleh sistem operasi (coba loop yang membuka file tanpa menutupnya!). Meskipun demikian, dalam praktiknya, tidak menutup file sering kali berhasil, saat Anda tidak membuka banyak file.
Eric O Lebigot
51

Ada pustaka bawaan yang disebut pickle. Menggunakan pickleAnda dapat membuang objek ke file dan memuatnya nanti.

import pickle

f = open('store.pckl', 'wb')
pickle.dump(obj, f)
f.close()

f = open('store.pckl', 'rb')
obj = pickle.load(f)
f.close()
Yossi
sumber
1
Saya menggunakan Python 3.4: f = open('store.pckl', 'wb')untuk membuka file yang akan ditulisi. Lihat stackoverflow.com/questions/13906623/… Dan gunakan `f = open ('store.pckl', 'rb') untuk membuka file untuk dibaca. Lihat stackoverflow.com/questions/7031699/… .
user3731622
apakah ini khusus untuk 3.4+? Saya hampir memilih jawaban bawah karena menghasilkan kesalahan saat Anda tidak menggunakan 'b'.
Wilmer E. Henao
12

Anda harus melihat modul rak dan acar . Jika Anda perlu menyimpan banyak data, mungkin lebih baik menggunakan database

John La Rooy
sumber
Saya ingin menyimpan satu objek yang masuk ke server cloud, untuk menangani jika saya masuk beberapa kali dari waktu ke waktu, server menolak permintaan saya. Apakah membuang objek ke dalam file menggunakan modul acar mungkin memiliki masalah keamanan? , misalnya jika seseorang mendapatkan objek yang saya buang, mereka dapat masuk ke penyimpanan cloud saya tanpa menggunakan kata sandi.
alper
5

Pendekatan lain untuk menyimpan banyak variabel ke file acar adalah:

import pickle

a = 3; b = [11,223,435];
pickle.dump([a,b], open("trial.p", "wb"))

c,d = pickle.load(open("trial.p","rb"))

print(c,d) ## To verify
Guruprasad Raghavan
sumber
4

Anda bisa menggunakan klepto, yang menyediakan cache persisten ke memori, disk, atau database.

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db['1'] = 1
>>> db['max'] = max
>>> squared = lambda x: x**2
>>> db['squared'] = squared
>>> def add(x,y):
...   return x+y
... 
>>> db['add'] = add
>>> class Foo(object):
...   y = 1
...   def bar(self, x):
...     return self.y + x
... 
>>> db['Foo'] = Foo
>>> f = Foo()
>>> db['f'] = f  
>>> db.dump()
>>> 

Kemudian, setelah juru bahasa restart ...

dude@hilbert>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('foo.txt')
>>> db
file_archive('foo.txt', {}, cached=True)
>>> db.load()
>>> db
file_archive('foo.txt', {'1': 1, 'add': <function add at 0x10610a0c8>, 'f': <__main__.Foo object at 0x10510ced0>, 'max': <built-in function max>, 'Foo': <class '__main__.Foo'>, 'squared': <function <lambda> at 0x10610a1b8>}, cached=True)
>>> db['add'](2,3)
5
>>> db['squared'](3)
9
>>> db['f'].bar(4)
5
>>> 

Dapatkan kodenya di sini: https://github.com/uqfoundation

Mike McKerns
sumber
7
OP tidak meminta built-in.
Mike McKerns
4

Pendekatan berikut tampaknya sederhana dan dapat digunakan dengan variabel dengan ukuran berbeda:

import hickle as hkl
# write variables to filename [a,b,c can be of any size]
hkl.dump([a,b,c], filename)

# load variables from filename
a,b,c = hkl.load(filename)
iblis secara detail
sumber
hicklepaket lebih kuat (lebih sedikit rawan kesalahan) dan bahkan lebih sederhana (lebih sedikit kode) daripada pickle.
pengguna2340939