🐍📓 Mi agenda Python: #4 Pickle

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@eniolw·
0.000 HBD
🐍📓 Mi agenda Python: #4 Pickle
<div class="text-center"><img src="https://i.postimg.cc/W4GGpWsY/banner.jpg"></div>

<h1>🐍📓 Mi agenda Python: #4 Pickle</h1>

<div class="pull-right"><p><br><i>Por Enio...</i></p></div>
<div>⁣</div>
<p><br></p>

<div class="text-justify">

<p>Nos vemos de nuevo, apreciados lectores y steemianos de #STEM-Espanol, #SteemSTEM, #Curie, #Utopian-io y otras comunidades de Steemit.</p>

<p>Continuamos con nuestra serie <b>Mi agenda Python</b>, enfocada en abordar distintas herramientas de programación relacionadas con el lenguaje de programación Python y que puede abarcar herramientas tales como <i>snippets</i>, <i>scripts</i>, bibliotecas (‘librerías’), <i>frameworks</i>, programas de aplicación, entre otros, siendo una serie que ya <a href="https://steemit.com/steemstem/@eniolw/-mi-agenda-python-1--1548901553">hemos presentado anteriormente</a> y en la que abordamos contenidos de manera accesible tanto para el público especialista como el no-especialista. Sin más preámbulos, revisemos la herramienta de esta edición.</p>

<hr>
<h2>Nombre del Recurso</h2>
<p><code>Pickle</code></p>

<hr>
<h2>Aclarando conceptos...</h2>

<p>La mayoría de los programas de aplicación de nuestro escritorio, móvil y casi todo aquel que sea usado a través de la Internet por lo general requiere un frecuente intercambio de información, bien sea enviando y recibiendo dicha información con relación a una fuente ajena (a través de una red) o con relación a una fuente propia que sea parte del sistema en el que se ejecuta el software.</p>

<p>En ambos casos, el intercambio de información muy probablemente implique un proceso de <b>almacenamiento</b>, es decir, que la información sea grabada en algún medio <b>medio de almacenamiento secundario</b>. Es a lo que comúnmente se refieren los usuarios finales cuando hablan de 'guardar y abrir archivos', pero que, no obstante, en ciencias y tecnologías de la computación resulta ser una operación conocida técnicamente como <b>persistencia</b>. Se dice que es persistencia en el sentido de que la información 'persiste' por tiempo prolongado y puede ser 'recuperada' para poder ser utilizada  nuevamente.</p>

<p>El origen de la persistencia le sucedió a la memoria RAM, que es la memoria principal del computador desde la época de John von Neumann y su aún-vigente arquitectura. Si bien la memoria RAM es la que carga los datos y programas, lo hace de manera temporal o mientras haya suministro eléctrico (la base de esta tecnología electrónica), de allí que sea altamente rápida, pero volátil. Para poder almacenar los datos independientemente de ello y con más duración se emplean memorias 'secundarias', las cuales hacen un buen trabajo para dar persistencia a la información.</p>

<p>No obstante, la memoria secundaria es demasiado lenta para la ejecución directa de programas. Por ejemplo, si usted lanza muchas aplicaciones en un hardware promedio, notará que mientas algunas se ejecutan bien, otras lo harán muy lentamente. Eso se explica no solamente por el hecho de que la memoria principal esté llena y ocupada con los otros varios programas, sino porque, para poder mantener todas las aplicaciones cargadas y en funcionamiento –como usted espera–, el sistema operativo está temporalmente almacenando la actividad de algunas de esas aplicaciones en el disco duro, el cual es un medio de almacenamiento secundario. Puesto que intercambiar la información temporal desde el disco duro es algo muy lento en comparación con el intercambio desde la memoria RAM, el desempeño será menos óptimo y provocará ese efecto de lentitud con algunos procesos.</p>

<p>Esta prestación que ofrecen los modernos sistemas operativos de apoyarse en la memoria secundaria para auxiliar a la memoria principal cuando esta se encuentra copada, y poder así mantener a flote las aplicaciones abiertas, se llama <b>memoria virtual</b> en el sistema Windows, y <b><i>swapping</i></b> en sistemas <i>UNIX-like</i> (tipo UNIX) como GNU/Linux. En la imagen siguiente vemos cómo el monitor de sistema de una de mis computadoras, en un momento determinado, muestra el uso del área de intercambio (<i>swapping</i>).</p>

<div class="text-center">
<img src="https://i.postimg.cc/bw20WYWh/intercambio.png" alt="Área de intercambio">
<br><sup><b>⬆️ Imagen 1:</b> Rendimiento de mi sistema operativo usando el área de intercambio <b>Autor:</b> @Eniolw <b>Licencia:</b> <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a></sup></div>

<br><p>Por supuesto, ello es un ejemplo del papel extendido de la memoria secundaria, que sin embargo, sigue teniendo como norte principal el <b>almacenamiento persistente de la información</b>.</p>

<p>Por lo general, los programas almacenan con persistencia todo aquello que constituya su base de datos o las bases de datos con las que tenga alguna relación, y tales datos dependerán en gran medida de lo que trate la aplicación, que puede ser muchas cosas, desde el simple estado de un videojuego, pasando por transacciones de negocios, hasta un <i>post</i> de Steemit, por ejemplo. Otro método para crear registros persistentes son los ficheros, los cuales forman parte del sistema de archivo del dispositivo de memoria secundaria.</p>

<p>No obstante, en ocasiones, algunos programas necesitarán almacenar en la memoria secundaria información más elaborada, como la de sus propios <b>estados internos</b>. Para un programador, esto se refiere a todos los valores e instancias de objetos que crea y conforma un programa en ejecución. Este tipo de información no es atómica o primitiva, es decir, no está descompuesta en partes indivisibles como pasa con los datos de la mayoría de las bases de datos, sino que es compuesta de varias partes que solo tienen sentido y operatividad en conjunto, por lo que a veces es mejor almacenarla permanentemente tal como está.</p>

<p>Por ejemplo, en una aplicación cliente de la <i>blockchain</i> podría existir un objeto llamado <i>post</i>, el cual posee atributos como título, cuerpo, etiquetas, autor, url, comentarios, recompensas, etc., los cuales, a su vez, pueden ser otros objetos. Los valores exactos que posee el objeto en cada uno de sus atributos en un entorno de ejecución y tiempo determinados le confiere identidad al objeto y constituye un <b>estado concreto</b>. Si uno de los valores es alterado, se dice que el estado no ha persistido, pues ha cambiado.</p>

<p>Dicho objeto puede almacenarse en una memoria secundaria, quizá a través de la descomposición y extracción de sus atributos para almacenarlos individualmente, lo que implica que deben unirse todas las piezas nuevamente a la hora de recuperar el estado, instanciando cada sub-objeto implicado. Esto puede ser conveniente en algunos casos, pero inconveniente en otros, sobre todo cuando se trata de transportar el objeto o si su recuperación implica invertir recursos de procesamiento.</p>

<p>Alternativamente está la <b>serialización</b>. Es una técnica mediante la cual los objetos se codifican a una secuencia de bytes tal como si fuesen una cadena de caracteres, de tal manera que pueden ser representados en una secuencia de datos que puede ser fácilmente escrita en un medio de memoria secundaria. De esta forma, los objetos y su estados pueden ser reconstruidos simplemente recuperando y decodificando la secuencia que los representa. Con esto tiene relación la operación de <i>swapping</i> mencionada anteriormente.</p>

<p>Además, la serialización aporta ventajas adicionales más que solamente almacenamiento, pues permite la <b>transferencia íntegra del objeto</b> a través de una red, quizá para enviarlo a un dispositivo remoto que ejecute una aplicación que lo necesite. En el ejemplo anterior sobre el objeto <i>post</i>, esto cobra sentido por cuanto muchas aplicaciones clientes de la <i>blockchain</i> del Steem pueden descargar la totalidad de la data que constituye a un post codificada en formato JSON y fácilmente reconstruirlo.</p>

<p>Ahora bien, <b>¿cómo se implementa la serialización?</b> Ello dependerá del lenguaje de programación empleado y nos servirá para presentar la herramienta de esta entrega.</p>

<hr>
<h2>Descripción</h2>

<p><b>Pickle</b> es un módulo de Python que viene incluido en su biblioteca estándar durante su instalación. Se dice que es un <b>'módulo'</b> puesto que es el término estandarizado dentro del mundo Python y es equivalente al concepto de <b>'biblioteca'</b> examinado en anteriores entregas; una colección de código con funciones prescritas que simplemente incluimos en nuestros proyectos para facilitar el desarrollo o aprovechar sus prestaciones.</p>

<p>El papel de Pickle es <b><em>proveer un método simple pero efectivo para llevar a cabo la serialización de objetos dentro de Python</em></b>. Para ello, Pickle hace la serialización a secuencias de bytes, escribiendolas y leyéndolas desde ficheros para su persistencia. El resultado de la operación, por tanto, será una cadena que generalmente se guarda a un archivo y al que podemos referirnos como <b>'archivo <i>pickle</i>'</b>.</p>

<p>La serialización puede realizarse como <b>representación de ASCII imprimible</b>, lo que permite que la codificación sea parcialmente legible para los seres humanos (útil en casos de depuración), o como <b>formato binario</b>, lo que sería ilegible para nosotros, pero implicaría eficiencia en el procesamiento.</p>

<p>Como hemos visto, los posibles usos de estos <i>pickes</i> de Python pueden abarcar desde el almacenamiento en ficheros y bases de datos de los datos-objetos producidos por la ejecución de un programa, la realización de copias de seguridad o la transferencia del objeto a través de Internet, etc.</p>

<p>Personalmente he encontrado a Pickle realmente práctico en algunos proyectos en los que puedo prescindir de una base de datos en beneficio de utilizar un archivo de texto plano, en el cual se almacena el estado del objeto sin necesidad de descomponerlo y de almacenar sus partes por separado para luego tener que cargarlas cada una y rearmar al objeto; hacer <i>pickles</i> realmente puede ser cómodo en muchos casos.</p>

<hr>
<h2>Algunas características</h2>
<ul>
<li>Al ser <b>estándar</b> no hace falta su instalación como módulo externo y viene incluido en todas las versiones de Python.</li>
<li>Su cometido es la <b>serialización</b>, pero no en todo el entendimiento de la persistencia como proceso, puesto que realmente no se ocupa de interactuar con el sistema de archivos de otra manera que no sea escribir y leer los datos a serializar.</li>
<li>Se apoya en un módulo interno llamado <b>marshal</b>, el cual realiza una tarea similar a Pickle y su nombre viene de <i>marshalling</i> que significa 'serialización' en inglés.</li>
<li>Posee una mucho más óptima <b>implementación en lenguaje C</b> conocida internamente como <a href="https://docs.python.org/2.2/lib/module-cPickle.html"> cPickle</a>, puesto que el módulo original de Python es más lento.</li>
<li>El formato que genera es específico para Python, por lo cual <b>puede ser utilizado exclusivamente dentro de este lenguaje</b>. Ello tiene la ventaja de que permite la serialización de objetos complejos y la desventaja de que las aplicaciones escritas con otros lenguajes no podrán entender ese formato.</li>
</ul>
<hr>
<h2>Sitio web o repositorio</h2>
<p><a href="https://docs.python.org/3/library/pickle.html">Biblioteca estándar de Python</a></p>

<hr>
<h2>Ejemplo de uso</h2>

<p></p>
<p>Veremos ahora una demostración de uso del módulo a modo de tutorial y ejemplo. Hemos dicho que Pickle viene incluido por defecto, por lo cual no hay que hacer pasos extra de instalación. Para usarlo simplemente importamos el módulo así:</p>

<pre><code>import pickle</code></pre>

<br><p>Ahora examinaremos cómo utilizar este módulo para hacer operaciones de <b>serialización (<i>pickling</i>)</b> y de <b>deserialización (<i>unpickling</i>)</b>. En primer lugar consideremos la siguiente clase <i>Post</i> y su objeto instancia:</p>

<pre><code>class Post:
    def __init__(self, _autor, _titulo, _contenido, _etiquetas, _permlink, _metadata):
        self.autor = _autor
        self.titulo = _titulo
        self.contenido = _contenido
        self.etiquetas = _etiquetas
        self.permlink = _permlink
        self.metadata = _metadata
<br>post = Post(
     "eniolw", 
     "Agenda Python: Pickle", 
     "...Contenido del post...", 
     ["steemstem", "stem-espanol"], 
     "asdawewdwefwegefe2343",
     {"app": "steemstem"}
)</code></pre>

<br><p>A fin de generar el fichero pickle, crearemos primero un archivo y lo abriremos en modo de escritura en binario. Lo correcto es hacerlo mediante la cláusula <code>with</code>. Luego, usamos la función <code>dump</code> (volcar) del módulo Pickle para poder hacer la serialización. Esta función toma dos argumentos: el <b>objeto a serializar</b> y el <b>destino</b>, que será el archivo creado previamente:</p>

<pre><code>with open("pickle_de_post", "wb") as archivo:
     pickle.dump(post, archivo)</code></pre>

<br><p>Si echamos un vistazo al archivo generado puede que, dependiendo del editor y su configuración, se decodifique y visualice con algunas secuencias legibles y otras parcialmente ilegibles o puede que muestre una serie de números hexadecimales.</p>

<p>Ahora bien, es útil saber que <b>se pueden serializar distintos objetos en el mismo fichero</b>, de modo que bajo la anterior cláusula <code>with</code>, podríamos volcar nuevos objetos. Por ejemplo:</p>

<pre><code>     pickle.dump({"nombre": "eniolw"}, archivo)
     pickle.dump({"pais": "Venezuela"}, archivo)
     pickle.dump({"blog": "https://steemit.com/@eniolw"}, archivo)</code></pre>

<br><p>También, es interesante señalar que <b>la serialización no necesariamente tiene que almacenarse en la memoria secundaria</b>, sino registrarla en una variable <b>string</b>. Para ello se usa la función <code>dumps</code>. Nótese que a diferencia de los ejemplos de arriba, esta función posee una <b>s</b> adicional, que viene de <i>string</i> (cadena de caracteres).</p>

<pre><code>post_s = pickle.dumps(post)</code></pre>

<br><p>Con ello podemos usar la variable <code>post_s</code> de distintas maneras, como enviarla por Internet.</p>

<p>Ahora bien, la operación inversa es la <b>deserialización</b>, llamada aquí <i>'unpickling'</i>. Se trata de decodificar correctamente todo el fichero para poder rearmar el objeto y cargarlo en la memoria principal. La función del módulo Pickle que sirve para eso es <i>load</i> (cargar) y se usa como sigue:</p>

<pre><code>with open("pickle_de_post", "rb") as archivo:
     post = pickle.load(archivo)</code></pre>

<br><p>Aquí, la variable <code>post</code> será el objeto deserializado de tipo <code>Post</code> (el primero incluido en el archivo). Si la clase se tratara de un diccionario de Python, podríamos fácilmente comprobarlo si imprimimos el objeto por la salida estándar. Sin embargo, los demás objetos serializados aún no se han recuperado. Para cargar cada uno habrá que ejecutar tantas veces <code>load</code> como veces se hizo <code>dump</code>:</p>

<pre><code>     dict1 = pickle.load(archivo)
     dict2 = pickle.load(archivo)
     dict3 = pickle.load(archivo)</code></pre>

<br><p>Alternativamente, el módulo Pickle posee las clases <b>Pickler</b> y <b>Unpickler</b>, con las cuales se puede hacer exactamente lo mismo que con las funciones mostradas en los <i>scripts</i> anteriores ya que estas últimas son, en realidad, atajos a las mencionadas clases.</p>

<p>Para cerrar, se inserta a continuación el <i>script</i> unificado con todo los códigos usados.</p>

<pre><code># Importanto el módulo:
import pickle
<br># Creando la clase de ejemplo:
class Post:
     def __init__(self, _autor, _titulo, _contenido, _etiquetas, _permlink, _metadata):
          self.autor = _autor
          self.titulo = _titulo
          self.contenido = _contenido
          self.etiquetas = _etiquetas
          self.permlink = _permlink
          self.metadata = _metadata
<br>def main():
<br>     # Instanciando el objeto de ejemplo:
     post = Post(
          "eniolw", 
          "Agenda Python: Pickle", 
          "...Contenido del post...", 
          ["steemstem", "stem-espanol"], 
          "asdawewdwefwegefe2343",
          {"app": "steemstem"}
     )
<br>     # Serializando el objeto post y otros en ficheros:
     with open("pickle_de_post", "wb") as archivo:
          pickle.dump(post, archivo)
          pickle.dump({"nombre": "eniolw"}, archivo)
          pickle.dump({"pais": "Venezuela"}, archivo)
          pickle.dump({"blog": "https://steemit.com/@eniolw"}, archivo)
<br>     # Deserializando desde ficheros:
     with open("pickle_de_post", "rb") as archivo:
          post = pickle.load(archivo)
          dict1 = pickle.load(archivo)
          dict2 = pickle.load(archivo)
          dict3 = pickle.load(archivo)
<br>     # Serializando sobre un string (dumps):
     post_s = pickle.dumps(post)
     print (post_s)
<br><br>if __name__ == '__main__':
     main()</code></pre>

<br><div class="text-center">
<img src="https://i.postimg.cc/mrf3sfWF/codigo1.png" alt="Script anterior en Sublime Text">
<br><sup><b>⬆️ Imagen 2:</b>  Script de demostración visualizado en Sublime Text <b>Autor:</b> @Eniolw <b>Licencia:</b> <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a></sup></div>

<hr>
<h2>En resumen</h2>

<p>Hemos visto que la <b>serialización</b> es una técnica de programación bastante práctica para codificar completos objetos y poder representarlos en su totalidad mediante una secuencia única de bytes, sin tener que descomponer y codificar por separado sus partes. El destino del serializado será, la mayoría de las veces, la <b>persistencia</b>, es decir, el almacenamiento prolongado del objeto, lo cual puede hacerse en una base de datos o en un archivo.</p>

<p>Esto es especialmente útil cuando <b>conviene preservar el estado exacto de un objeto</b> para que pueda ser reutilizado posteriormente o incluso transmitido remotamente. Un ámbito en el cual se aplica la serialización son las operaciones de <i>swapping</i> que realiza el sistema operativo cuando respalda en la memoria secundaria el estado de muchas aplicaciones que no puede mantener por completo en la memoria física principal.</p>

<p>La herramienta de fábrica que posee Python para la serialización es <b>Pickle</b>, un módulo con el cual se generan secuencias en un formato propio que puede representar muchos objetos complejos. Adicionalmente, Pickle aplica el <b>volcado sobre archivos</b> para su persistencia, como también puede mantener la secuencia como <b><i>string</i></b>; como prefiera y necesite el programador. Pickle proporciona soluciones prácticas, y cuenta con una implementación en lenguaje C que, de acuerdo a su documentación, es "hasta 1000 veces más eficiente" que la implementación original de Python, pero que naturalmente puede ser invocada y utilizada desde este.</p>

<p>En el futuro continuaremos abordando más herramientas de Python. De momento, si tienes alguna duda o aporte, no dudes en hacerlo saber. Nos vemos.</p>

</div>

<hr>
<div class="text-justify">
<p><b>ALGUNAS FUENTES DE CONSULTA</b></p>
<ul>
<li><a href="https://docs.python.org/3/library/pickle.html">Documentación oficial de Pickle (en inglés).</a></li>
</ul>
</div>
<hr>
<div class="text-justify"><p><em>Si estás interesado en más temas sobre Ciencia, Tecnología, Ingeniería y Matemáticas (STEM, siglas en inglés), consulta las etiquetas #STEM-Espanol y #SteemSTEM, donde puedes encontrar más contenido de calidad y también hacer tus aportes. Puedes unirte al <a href="https://discord.gg/bw6aH9W">servidor de Discord</a> de STEM-Espanol para participar aún más en nuestra comunidad y consultar los reportes semanales publicados por @STEM-Espanol.</em></p></div>

<hr>
<div class="text-center"><img src="https://steemitimages.com/0x0/https://i.imgur.com/Mlgwrhf.jpg">
<br><sup><b>Créditos:</b> @IAmPhysical</sup></div>

<div class="text-center"><img src="https://i.postimg.cc/xCf7bHT4/logo-con-base1.png">
<br><sup><b>Créditos:</b> @Eniolw</sup></div>

<hr>
<div class="text-justify">
<p><br><b>NOTAS ACLARATORIAS</b></p>
<ul>
<li>La imagen de pie es de @CarlosERP-2000 y @IAmPhysical y es de dominio público.</li>
<li>A menos que haya sido indicado lo contrario, las imágenes de esta publicación han sido elaboradas por el autor, lo que incluye la imagen de <i>banner</i>, creada con base en imágenes de dominio público y en un logo de Python adaptado por <a href="https://commons.wikimedia.org/wiki/User:Rocket000">Rocket000</a> y otros (<a href="https://commons.wikimedia.org/wiki/File:Python.svg">fuente</a>).</li>
</ul>
</div>
<div class="text-center"><img src="https://steemitimages.com/0x0/http://i.picasion.com/pic87/f6171e50de4ba9ae17c018b092dc3b1d.gif" alt="imagen de pie"></div>
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,