Guardando y recuperando datos en Python usando Pickle

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.