Muy fácil de usar. Aquí les muestro como grabar un objeto (Account) el cual tiene otros objetos adentro (lista de objetos tipo ‘Transaction’).
#!/usr/bin/env python3
# @author Jose Vicente Nunez - josevnz@kodeek.com
import os, os.path, pickle, tempfile
class Transaction:
def __init__(self, amount, date, currency="USD", conv_rate=1.0, description=None):
self.__amount = amount
self.__date = date
self.__currency = currency
if conv_rate < 0:
raise ValueError("Invalid amount:{0}".format(conv_rate))
self.__conv_rate = float(conv_rate)
self.__description = description
@property
def amount(self):
return self.__amount
@property
def date(self):
return self.__date
@property
def currency(self):
return self.__currency
@property
def description(self):
return self.__description
@property
def conv_rate(self):
return self.__conv_rate
@property
def usd(self):
return self.__conv_rate * self.__amount
class Account:
def __init__(self, number, name, transactions = []):
self.__number = number
self.__name = name
if transactions == None:
self.__transactions = []
else:
self.__transactions = transactions
@property
def number(self):
return self.__number
@property
def name(self, name):
if name == None:
return self.__name
if len(name) < 6:
raise ValueError("Account name too short!")
self.__name = name
def __len__(self):
return len(self.__transactions)
@property
def name(self):
return self.__name
@property
def balance(self):
balance = 0
for bal in self.__transactions:
balance += bal.usd
return balance
@property
def all_usd(self):
return len([t for t in self.__transactions if t.currency == "USD"]) == len(self.__transactions)
def apply(self, transaction):
if not isinstance(transaction, Transaction):
raise ValueError("Invalid argument, can only add transactions!")
self.__transactions.append(transaction)
def __getFilename(self):
return os.path.join(tempfile.gettempdir(), str(self.number))
def save(self):
fn = self.__getFilename()
fh = None
try:
fh = open(fn, 'wb')
pickle.dump([self.__name, self.__number, self.__transactions], fh, pickle.HIGHEST_PROTOCOL)
except (EnvironmentError, pickle.PicklingError) as Error:
raise SaveError(str(err))
finally:
if fh is not None:
fh.close()
def load(self):
fn = self.__getFilename()
fh = None
try:
fh = open(fn, 'rb')
(self.__name, self.__number, self.__transactions) = pickle.load(fh)
except (EnvironmentError, pickle.UnpicklingError) as Error:
raise LoadError(str(err))
finally:
if fh is not None:
fh.close()
if __name__ == "__main__":
transactions = []
transactions.append(
Transaction(
15.0,
"06-06-1966",
"USD",
1.0,
description="XXXX paid me some money"))
transactions.append(
Transaction(
-2,
"06-06-1966",
"USD",
1.0,
description="I had to pay YYYYY some cash"))
transactions.append(
Transaction(
10000,
"06-06-1966",
"BsF",
0.0001,
description="Maduro paid me some money in Venezuelan BS. LOL"))
account = Account(666666, "Savings account", transactions)
account.apply(Transaction(-3, "02-28-1016", "USD", 1.0, "Coffee time"))
print(
"'{0}' Balance: ${1}, all in USD: {2}".format(
account.name,
account.balance,
account.all_usd))
account.save()
account.load()
print(
"'{0}' Balance: ${1}, all in USD: {2}".format(
account.name,
account.balance,
account.all_usd))
Pickle no es seguro (ya que se lleva a cabo ninguna validación en el código leido desde el archivo), sin embargo es increíblemente conveniente para programas pequeños que requieren guardar datos rápidamente con estructuras de datos complejas, como por ejemplo objetos anidados.