Ben böyle bir nesne yarattım:
company1.name = 'banana'
company1.value = 40
Bu nesneyi kaydetmek istiyorum. Bunu nasıl yapabilirim?
protocol=pickle.HIGHEST_PROTOCOL
. Cevabım turşu için de alternatifler sunuyor.
Ben böyle bir nesne yarattım:
company1.name = 'banana'
company1.value = 40
Bu nesneyi kaydetmek istiyorum. Bunu nasıl yapabilirim?
protocol=pickle.HIGHEST_PROTOCOL
. Cevabım turşu için de alternatifler sunuyor.
Yanıtlar:
Sen kullanabilirsiniz pickle
standart kütüphanede modülü. İşte örneğinize temel bir uygulama:
import pickle
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
with open('company_data.pkl', 'wb') as output:
company1 = Company('banana', 40)
pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL)
company2 = Company('spam', 42)
pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL)
del company1
del company2
with open('company_data.pkl', 'rb') as input:
company1 = pickle.load(input)
print(company1.name) # -> banana
print(company1.value) # -> 40
company2 = pickle.load(input)
print(company2.name) # -> spam
print(company2.value) # -> 42
Ayrıca, bir dosyayı açan ve ona tek bir nesne yazan aşağıdaki gibi kendi basit yardımcı programınızı tanımlayabilirsiniz:
def save_object(obj, filename):
with open(filename, 'wb') as output: # Overwrites any existing file.
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
# sample usage
save_object(company1, 'company1.pkl')
Bu çok popüler bir cevap olduğu için, biraz gelişmiş kullanım konularına değinmek istiyorum.
cPickle
(veya _pickle
) vspickle
Birincisi C ile yazılmış ve çok daha hızlı olduğu için cPickle
modülü kullanmak her zaman tercih edilir pickle
. Aralarında bazı ince farklılıklar vardır, ancak çoğu durumda eşdeğerdirler ve C versiyonu büyük ölçüde üstün performans sağlar. Buna geçmek daha kolay olamazdı, import
ifadeyi şu şekilde değiştirin :
import cPickle as pickle
Python 3'te cPickle
yeniden adlandırıldı _pickle
, ancak pickle
modül artık otomatik olarak yaptığı için bunu yapmak artık gerekli değil - python 3'te turşu ve _pickle arasındaki fark nedir? .
Yıkık, kodunuzun hem Python 2 hem de 3'te mevcut olduğunda her zaman C sürümünü kullanmasını sağlamak için aşağıdaki gibi bir şey kullanabilmenizdir:
try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
pickle
okumak ve birkaç farklı yazma dosyaları, Python özgü, biçimleri denilen protokolleri anlatıldığı gibi belgeler , "Protokolü sürüm 0" ASCII ve bu nedenle "insan tarafından okunabilir" dir. > 0 sürümleri ikiliktir ve kullanılabilir en yüksek sürüm Python'un hangi sürümünün kullanıldığına bağlıdır. Varsayılan değer Python sürümüne de bağlıdır. Python 2'de varsayılan Protokol sürümüdür 0
, ancak Python 3.8.1'de Protokol sürümüdür 4
. Python 3.x'de modülün bir eki vardı pickle.DEFAULT_PROTOCOL
, ancak bu Python 2'de mevcut değil.
Neyse ki pickle.HIGHEST_PROTOCOL
, her çağrıda yazmak için kısayol vardır (istediğiniz şey olduğunu ve genellikle yaptığınızı varsayarak), -1
bir dizinin son öğesine negatif bir dizin yoluyla başvurmaya benzer şekilde sadece değişmez sayıyı kullanın . Yani, yazmak yerine:
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
Sadece şunu yazabilirsiniz:
pickle.dump(obj, output, -1)
Her iki durumda da, Pickler
çoklu turşu işlemlerinde kullanmak için bir nesne oluşturduysanız protokolü yalnızca bir kez belirtmeniz gerekir :
pickler = pickle.Pickler(output, -1)
pickler.dump(obj1)
pickler.dump(obj2)
etc...
Not : Python'un farklı sürümlerini çalıştıran bir ortamdaysanız, muhtemelen hepsinin okuyabileceği belirli bir protokol numarasını açıkça kullanmak (yani sabit kod) kullanmak istersiniz (sonraki sürümler genellikle önceki sürümler tarafından üretilen dosyaları okuyabilir) .
Turşu dosyası iken olabilir bunlardan bilinmeyen numara varken, yukarıdaki örneklerde görüldüğü gibi salamura nesnelerin herhangi sayısına sahiptirler, bu değişken boyutlu konteynerin çeşit saklayabilir bir benzeri genellikle daha kolaydır list
, tuple
ya dict
ve yazma hepsini tek bir çağrıda dosyaya aktarın:
tech_companies = [
Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18)
]
save_object(tech_companies, 'tech_companies.pkl')
ve listeyi ve içindeki her şeyi daha sonra geri yükleyin:
with open('tech_companies.pkl', 'rb') as input:
tech_companies = pickle.load(input)
Önemli bir avantajı (yani bilgi olmadan bunu yaparken her ne kadar daha sonra onları geri yüklemek için kaydedilmiş kaç nesne örnekleri bilmek gerekmez olduğunu ise mümkün, bazı hafif uzman kod gerektirir). İlgili sorunun yanıtlarına bakın Turşu dosyasında birden çok nesne kaydetme ve yükleme? bunu yapmanın farklı yollarıyla ilgili ayrıntılar için. Şahsen ben @Lutz Prechelt'in en iyi cevabını seviyorum . İşte buradaki örneklere uyarlanmıştır:
class Company:
def __init__(self, name, value):
self.name = name
self.value = value
def pickled_items(filename):
""" Unpickle a file of pickled data. """
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
print('Companies in pickle file:')
for company in pickled_items('company_data.pkl'):
print(' name: {}, value: {}'.format(company.name, company.value))
company1
ve company2
. Neden Company
ne olduğunu silmiyor ve göstermiyorsun?
Bence nesnenin bir olduğunu varsaymak oldukça güçlü bir varsayım class
. Ya bir değilse class
? Ayrıca nesnenin yorumlayıcıda tanımlanmadığı varsayımı vardır. Tercümanda tanımlanmışsa ne olur? Ayrıca, öznitelikler dinamik olarak eklenirse ne olur? Bazı python nesneleri __dict__
oluşturulduktan sonra eklenmiş özniteliklere sahip olduğunda pickle
, bu özniteliklerin eklenmesine saygı göstermez (yani, eklendikleri 'unutur' - çünkü pickle
nesne tanımına referansla serileştirir).
Tüm bu durumlarda pickle
ve cPickle
korkunç bir şekilde başarısız olabilir.
object
(Keyfi olarak oluşturulmuş) bir özellik kaydetmek istiyorsanız (nesne tanımına eklenmiş veya daha sonra)… dill
python'da neredeyse her şeyi serileştirebilecek en iyi bahsiniz kullanmaktır .
Bir sınıfla başlıyoruz…
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import pickle
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>> with open('company.pkl', 'wb') as f:
... pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL)
...
>>>
Şimdi kapat ve yeniden başlat ...
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import pickle
>>> with open('company.pkl', 'rb') as f:
... company1 = pickle.load(f)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global
klass = self.find_class(module, name)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class
klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'Company'
>>>
Hata ... pickle
başa çıkamıyor. Deneyelim dill
. lambda
İyi bir ölçü için başka bir nesne türü (a ) atacağız .
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import dill
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> with open('company_dill.pkl', 'wb') as f:
... dill.dump(company1, f)
... dill.dump(company2, f)
...
>>>
Ve şimdi dosyayı okuyun.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import dill
>>> with open('company_dill.pkl', 'rb') as f:
... company1 = dill.load(f)
... company2 = dill.load(f)
...
>>> company1
<__main__.Company instance at 0x107909128>
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>>
İşe yarıyor. Nedeni pickle
başarısız olur ve dill
yapmaz, bir modül gibi dill
davranır __main__
(çoğunlukla) ve aynı zamanda referansla dekapaj yapmak yerine sınıf tanımlarını da seçebilir (olduğu gibi pickle
). A dill
turşusunun sebebi , lambda
ona bir isim vermesidir… daha sonra dekapaj büyüsü olabilir.
Aslında, özellikle oluşturduğunuz çok sayıda nesneniz varsa, tüm bu nesneleri kaydetmenin daha kolay bir yolu vardır. Sadece tüm python oturumunu boşaltın ve daha sonra tekrar gelin.
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import dill
>>> class Company:
... pass
...
>>> company1 = Company()
>>> company1.name = 'banana'
>>> company1.value = 40
>>>
>>> company2 = lambda x:x
>>> company2.name = 'rhubarb'
>>> company2.value = 42
>>>
>>> dill.dump_session('dill.pkl')
>>>
Şimdi bilgisayarınızı kapatın, bir espresso veya başka bir şeyin tadını çıkarın ve daha sonra tekrar gelin ...
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[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.
>>> import dill
>>> dill.load_session('dill.pkl')
>>> company1.name
'banana'
>>> company1.value
40
>>> company2.name
'rhubarb'
>>> company2.value
42
>>> company2
<function <lambda> at 0x1065f2938>
Tek büyük dezavantajı, dill
python standart kütüphanesinin bir parçası olmamasıdır. Eğer sunucunuza bir python paketi yükleyemezseniz, onu kullanamazsınız.
Sisteminizde piton paketlerini yüklemek edebiliyoruz Ancak, son alabilirsiniz dill
ile git+https://github.com/uqfoundation/dill.git@master#egg=dill
. Ve ile en son yayınlanan sürümü alabilirsiniz pip install dill
.
TypeError: __new__() takes at least 2 arguments (1 given)
kullanmaya çalışırken bir alıyorum dill
.
TypeError
Tam olarak ne yaptığını anlıyor musun? Bu genellikle bir sınıf örneğini başlatırken yanlış sayıda argümana sahip olmanın bir işaretidir. Bu, yukarıdaki sorunun iş akışının bir parçası değilse, başka bir soru olarak gönderebilir, bana e-posta ile gönderebilir veya dill
github sayfasına bir sorun olarak ekleyebilir misiniz?
dill
sorun değildi .
dil
MemoryError
Yine de bana veriyorum! yapar cPickle
, pickle
ve hickle
.
İşi sizin için yapmak için anycache kullanabilirsiniz . Tüm ayrıntıları dikkate alır:
pickle
modülünü işlemek lambda
ve tüm güzel python özelliklerini genişletir .Örneği myfunc
oluşturan bir fonksiyonunuz olduğunu varsayarsak :
from anycache import anycache
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
@anycache(cachedir='/path/to/your/cache')
def myfunc(name, value)
return Company(name, value)
Anycache myfunc
ilk kez çağırır ve dosya cachedir
adı olarak benzersiz bir tanımlayıcı (işlev adına ve bağımsız değişkenlerine bağlı olarak ) kullanarak sonucu bir dosyaya alır . Ardışık herhangi bir çalışmada, turşu nesnesi yüklenir. Eğer cachedir
piton koşular arasında korunur, turşu nesne önceki piton vadede alınır.
Daha fazla ayrıntı için belgelere bakın
anycache
Örneğin, a class
veya kapsayıcı gibi birden fazla örneğini kaydetmek için nasıl kullanılır list
(bir işlev çağrılmasının sonucu değildi)?
company1
Sorunuzdan python3 ile hızlı örnek .
import pickle
# Save the file
pickle.dump(company1, file = open("company1.pickle", "wb"))
# Reload the file
company1_reloaded = pickle.load(open("company1.pickle", "rb"))
Ancak, bu cevabın belirttiği gibi, turşu sık sık başarısız olur. Yani gerçekten kullanmalısın dill
.
import dill
# Save the file
dill.dump(company1, file = open("company1.pickle", "wb"))
# Reload the file
company1_reloaded = dill.load(open("company1.pickle", "rb"))