Làm cách nào để lưu và khôi phục nhiều biến trong python?


104

Tôi cần lưu khoảng một chục đối tượng vào một tệp và sau đó khôi phục chúng sau. Tôi đã cố gắng sử dụng vòng lặp for với dưa chua và giá đỡ nhưng nó không hoạt động đúng.

Biên tập.
Tất cả các đối tượng mà tôi đang cố gắng lưu đều thuộc cùng một lớp (lẽ ra tôi nên đề cập đến vấn đề này trước đây), và tôi không nhận ra rằng mình có thể lưu cả lớp như thế này:

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'

1
Bạn nói rằng bạn đã thử một vòng lặp for. Vui lòng đăng mã đó và tại sao "nó không hoạt động đúng" (tức là, điều gì đã xảy ra và điều bạn muốn xảy ra).
Blair

Nếu bạn đang ở trên cửa sổ, hãy chắc chắn để mở các tập tin trong chế độ nhị phân
John La Rooy

@gnibbler: chế độ nhị phân chỉ cần thiết cho các giao thức không mặc định ( docs.python.org/library/pickle.html#usage ).
Eric O Lebigot

Câu trả lời:


170

Nếu bạn cần lưu nhiều đối tượng, bạn có thể chỉ cần đặt chúng vào một danh sách duy nhất, hoặc bộ sưu tập, ví dụ:

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)

Nếu bạn có nhiều dữ liệu, bạn có thể giảm kích thước tệp bằng cách chuyển protocol=-1đến dump(); picklesau đó sẽ sử dụng giao thức tốt nhất hiện có thay vì giao thức lịch sử mặc định (và tương thích ngược hơn). Trong trường hợp này, tệp phải được mở ở chế độ nhị phân ( wbrb, tương ứng).

Chế độ nhị phân cũng nên được sử dụng với Python 3, vì giao thức mặc định của nó tạo ra dữ liệu nhị phân (tức là không phải văn bản) (chế độ ghi 'wb'và chế độ đọc 'rb').


12
Trong Python 3.5, tôi phải mở tệp ở chế độ "byte", ví dụ: with open('objs.pickle', 'wb') as f:(lưu ý wb).
kbrose

Xin chào @Eric, with open('objs.pkl') as f:đơn giản là cần so sánh với những obj1, obj2 = pickle.load(open("objs.pkl","rb"))gì? Có sự khác biệt nào giữa hai điều này?
balandongiv

Với hình thức thứ hai bạn không đóng tệp. Đây không được coi là phương pháp hay, vì số lượng tệp mà bạn có thể mở song song thường khá hạn chế bởi hệ điều hành (hãy thử một vòng lặp mở tệp mà không đóng chúng!). Điều đó nói rằng, trong thực tế, không đóng tệp thường hoạt động, khi bạn không mở nhiều tệp.
Eric O Lebigot

49

Có một thư viện tích hợp được gọi là pickle. Sử dụng, picklebạn có thể kết xuất các đối tượng vào một tệp và tải chúng sau.

import pickle

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

f = open('store.pckl', 'rb')
obj = pickle.load(f)
f.close()

1
Tôi sử dụng Python 3.4: f = open('store.pckl', 'wb')để mở một tệp để ghi vào. Tham khảo stackoverflow.com/questions/13906623/… Và sử dụng `f = open ('store.pckl', 'rb') để mở một tệp để đọc từ đó. Tham khảo stackoverflow.com/questions/7031699/… .
user3731622

cái này có cụ thể cho 3,4+ không? Tôi gần như bỏ phiếu cho câu trả lời vì nó tạo ra lỗi khi bạn không sử dụng 'b'.
Wilmer E. Henao

12

Bạn nên nhìn vào xiêndưa mô-đun. Nếu bạn cần lưu trữ nhiều dữ liệu thì tốt hơn nên sử dụng cơ sở dữ liệu


Tôi muốn lưu một đối tượng duy nhất đăng nhập vào máy chủ đám mây, để xử lý nếu tôi đăng nhập nhiều lần theo thời gian, máy chủ từ chối yêu cầu của tôi. Việc kết xuất một đối tượng vào một tệp bằng mô-đun pickle có thể có bất kỳ vấn đề bảo mật nào không? , chẳng hạn như trường hợp nếu ai đó có được đối tượng được kết xuất của tôi, họ có thể đăng nhập vào bộ nhớ đám mây của tôi mà không cần sử dụng mật khẩu.
alper

5

Một cách tiếp cận khác để lưu nhiều biến vào một tệp pickle là:

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

4

Bạn có thể sử dụng klepto, cung cấp bộ nhớ đệm liên tục vào bộ nhớ, đĩa hoặc cơ sở dữ liệu.

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

Sau đó, sau khi trình thông dịch khởi động lại ...

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

Nhận mã tại đây: https://github.com/uqfoundation


7
OP không yêu cầu tích hợp sẵn.
Mike McKern

4

Cách tiếp cận sau có vẻ đơn giản và có thể được sử dụng với các biến có kích thước khác nhau:

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)

hicklegói mạnh mẽ hơn (ít bị lỗi hơn) và thậm chí đơn giản hơn (ít mã) hơn pickle.
user2340939
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.