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 picklestandart 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) vspickleBirincisi C ile yazılmış ve çok daha hızlı olduğu için cPicklemodü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ı, importifadeyi şu şekilde değiştirin :
import cPickle as pickle
Python 3'te cPickleyeniden adlandırıldı _pickle, ancak picklemodü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
pickleokumak 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), -1bir 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, tupleya dictve 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))
company1ve company2. Neden Companyne 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ü picklenesne tanımına referansla serileştirir).
Tüm bu durumlarda pickleve cPicklekorkunç 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)… dillpython'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 ... picklebaş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 picklebaşarısız olur ve dillyapmaz, bir modül gibi dilldavranı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 dillturşusunun sebebi , lambdaona 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ı, dillpython 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 dillile 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.
TypeErrorTam 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 dillgithub sayfasına bir sorun olarak ekleyebilir misiniz?
dillsorun değildi .
dilMemoryErrorYine de bana veriyorum! yapar cPickle, pickleve hickle.
İşi sizin için yapmak için anycache kullanabilirsiniz . Tüm ayrıntıları dikkate alır:
picklemodülünü işlemek lambdave tüm güzel python özelliklerini genişletir .Örneği myfuncoluş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 myfuncilk kez çağırır ve dosya cachediradı 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 cachedirpiton 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 classveya 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)?
company1Sorunuzdan 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"))