<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Bitácora de Vuelo (Publicaciones sobre binario)</title><link>http://blog.taniquetil.com.ar/</link><description></description><atom:link href="http://blog.taniquetil.com.ar/categories/binario.xml" rel="self" type="application/rss+xml"></atom:link><language>es</language><copyright>Contents © 2023 &lt;a href="mailto:facundo@taniquetil.com.ar"&gt;Facundo Batista&lt;/a&gt; CC BY-NC-SA</copyright><lastBuildDate>Mon, 29 May 2023 18:51:47 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Encapsulando Python en un binario</title><link>http://blog.taniquetil.com.ar/posts/0531/</link><dc:creator>Facundo Batista</dc:creator><description>&lt;p&gt;Este es un lindo truquito que no es de mi autoría, sino que es de John Lenton (él lo mostró en una reunión del laburo), pero como yo ya lo mostré en PyCon Brasil el año pasado, y en PyCon Argentina ayer, lo pongo acá para el que lo quiera mirar...&lt;/p&gt;
&lt;p&gt;Arrancamos con nuestro programa o proyecto Python que queremos meter adentro del binario... para nuestro ejemplo acá, crearemos un directorio, lo hacemos paquete de Python, y adentro creamos lo que sería el programa principal de nuestro sistema, con una función adentro que es la que arrancaría todo:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ mkdir proyecto
facundo@exopus:~/prueba$ cd proyecto/
facundo@exopus:~/prueba/proyecto$ touch __init__.py
facundo@exopus:~/prueba/proyecto$ cat principal.py
def run():
    print "Arrancamos!"
facundo@exopus:~/prueba/proyecto$ cd ..
facundo@exopus:~/prueba$&lt;/pre&gt;
&lt;p&gt;Tenemos que probar que podamos arrancar nuestro sistema desde el directorio padre... a veces no es tan fácil, hay que jugar un poquito con los paths de dónde importamos cosas, pero en este ejemplo es sencillo. Pero podemos probarlo facilmente:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ python
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)
...
&amp;gt;&amp;gt;&amp;gt; import proyecto.principal
&amp;gt;&amp;gt;&amp;gt; proyecto.principal.run()
Arrancamos!
&amp;gt;&amp;gt;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Una vez que lo logremos ejecutar así, tenemos que poner ese mismo código en un archivo con nombre &lt;code class="docutils literal"&gt;__main__.py&lt;/code&gt; en el directorio padre de nuestro proyecto:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ cat __main__.py
import proyecto.principal
proyecto.principal.run()&lt;/pre&gt;
&lt;p&gt;Volvemos a probar que nuestro sistema funciona correctamente:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ python __main__.py
Arrancamos!&lt;/pre&gt;
&lt;p&gt;El próximo paso es meter todo adentro de un archivo ZIP, aprovechando que Python es capaz de interpretar directamente este tipo de archivos comprimidos (por eso el nombre especial de antes, para que Python lo reconozca):&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ zip -r proyecto.zip __main__.py proyecto/
 adding: __main__.py (deflated 27%)
 adding: proyecto/ (stored 0%)
 adding: proyecto/__init__.py (stored 0%)
 adding: proyecto/principal.pyc (deflated 45%)
 adding: proyecto/__init__.pyc (deflated 30%)
 adding: proyecto/principal.py (stored 0%)&lt;/pre&gt;
&lt;p&gt;Probamos nuevamente que, hasta acá, funcione todo correctamente:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ python proyecto.zip
Arrancamos!&lt;/pre&gt;
&lt;p&gt;Finalmente, metemos todo eso adentro de un binario, indicando que se va a interpretar con Python, y haciéndolo ejecutable:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ ( echo '#!/usr/bin/env python'; cat proyecto.zip ) &amp;gt; miproyecto
facundo@exopus:~/prueba$ chmod +x miproyecto&lt;/pre&gt;
&lt;p&gt;¡Ya está! Ahora podemos ejecutar ese binario, como cualquier otro binario, y realmente estaremos ejecutando nuestro proyecto Python:&lt;/p&gt;
&lt;pre class="literal-block"&gt;facundo@exopus:~/prueba$ ./miproyecto
Arrancamos!&lt;/pre&gt;
&lt;p&gt;Genial, :)&lt;/p&gt;</description><category>binario</category><category>freeze</category><category>hack</category><guid>http://blog.taniquetil.com.ar/posts/0531/</guid><pubDate>Sat, 24 Sep 2011 23:00:25 GMT</pubDate></item><item><title>Decimal, binario y el asado</title><link>http://blog.taniquetil.com.ar/posts/0292/</link><dc:creator>Facundo Batista</dc:creator><description>&lt;p&gt;&lt;em&gt;Resulta que era sábado a la noche, no tenía mucho que hacer porque Moni estaba en Bariloche, y hubo una pregunta interesante en la lista de PyAr. Y la respuesta me salió bastante bizarra, en general fue bastante comentada. Motivado por un comentario en la reunión del otro día, la busqué y la releí (por primera vez). Y como me causó gracia, la rescato acá. La pregunta era por qué al redondear 39.285714285714285, el usuario no veía un 39.29, sino algo raro&lt;/em&gt;:&lt;/p&gt;
&lt;pre class="literal-block"&gt;&amp;gt; Sin redondear:
&amp;gt;
&amp;gt; &amp;gt;&amp;gt;&amp;gt; chargeandprop("EEARGPLRGKGDQKSAVSQKPRSRGILH")[1]
&amp;gt; 39.285714285714285
&amp;gt;
&amp;gt; Con round a 2 decimales:
&amp;gt;
&amp;gt; &amp;gt;&amp;gt;&amp;gt; round(chargeandprop("EEARGPLRGKGDQKSAVSQKPRSRGILH")[1],2)
&amp;gt; 39.289999999999999&lt;/pre&gt;
&lt;p&gt;El detalle acá es que te están mostrando un número binario en su forma decimal. ¿Por qué en forma decimal? Porque hace rato que tenemos 10 dedos en las manos, y contar en esa base nos es natural. ¿Por qué el número es binario? Parecerá arcaico a esta altura, pero seguimos teniendo procesadores que trabajan en forma binaria: a nivel de silicio la FPU (floating point unit) de tu micro guarda el nro en binario.&lt;/p&gt;
&lt;p&gt;Hagamos una analogía, para que resulte más fácil de entender. Viene tu sobrinito de 12 años, y te dice "tío, tío, enseñame algo que no entiendo de matemática". Vos, envalentonado por demostrar tus conocimientos, y viendo que es la única manera de salvar el fin de semana luego de que Argentina haya perdido 3 a 0 en la Copa América, le contestás "Obvio, lo que quieras". Entonces tu sobrino te da un lápiz y un papel y te dice... "escribí 'un tercio'".&lt;/p&gt;
&lt;p&gt;Vos sonreís, aunque una gota resbala sobre tu frente, temiendo lo peor, y le escribís, con suspenso, un "1/3". El nene, casi como un enviado del diablo (no reconocés tanta maldad en sus ojos), sonríe levemente, sabiendo que caíste en su trampa, y que a partir de ahí él seguirá subiendo y vos en decadencia, y te dice "no, pero con coma".&lt;/p&gt;
&lt;p&gt;Entonces, vos, con una cintura hábil, luego de tantos años de enfrentarte con la AFIP, le escribís un "0,3...". Y cuando casi empezás a explicarle el significado de los tres puntos, el te sacude un lapidario "no, pero hasta el final". Ahí vos sabés que perdiste, de que no hay una maldita manera de escribir infinitos 3, y menos en una sola hoja, y le contestás "no, nene, las gallinitas no hablan", y te vas a revisar como anda el asado.&lt;/p&gt;
&lt;p&gt;Ok, el procesador hace algo parecido, pero en binario. Cuando vos en decimal le decís redondeame un "39.285" a dos decimales, el tipo intenta anotar un "39.29" en su lápiz y papel binario, pero no puede. Aunque a nosotros, &lt;em&gt;ese&lt;/em&gt; nro nos resulta fácil, a él no, porque a nivel binario no tiene suficientes dígitos para escribirlo.&lt;/p&gt;
&lt;p&gt;Quizás porque esté programado así, o quizás porque no tiene un asado que atender, la FPU hace su mejor esfuerzo y guarda internamente el número más cercano al "39.29". Y eso es:&lt;/p&gt;
&lt;pre class="literal-block"&gt;&amp;gt;&amp;gt;&amp;gt; 39.29
39.289999999999999&lt;/pre&gt;
&lt;p&gt;Acá entra Python, quien en el intérprete interactivo, te muestra "la realidad posta posta, patente patente" (en inglés esta frase es distinta). Escribir directamente el nro, es como llamar a la función repr(), quien es lo más fiel posible con el ordenamiento de los átomos en el Universo:&lt;/p&gt;
&lt;pre class="literal-block"&gt;&amp;gt;&amp;gt;&amp;gt; repr(39.29)
'39.289999999999999'&lt;/pre&gt;
&lt;p&gt;Ahora, si vos querés ser engañado, podés decirle a Python que te muestre algo más humano. ¿Cómo le decís que te convierta un objeto a su representación en cadena de texto de una forma más "humana"? Con str():&lt;/p&gt;
&lt;pre class="literal-block"&gt;&amp;gt;&amp;gt;&amp;gt; str(39.29)
'39.29'&lt;/pre&gt;
&lt;p&gt;Ahí, lo que hace Python, sabiendo en parte cómo funcionan las FPU de nuestra época, y en parte porque aunque vayas ahora a revisar el asado los chorizos están quemados y los chinchulines te apagaron el fuego, es "redondear" ese nro a los quinces dígitos decimales.&lt;/p&gt;
&lt;p&gt;Notar que el statement "print" llama automáticamente a str() para convertir los objetos a mostrar:&lt;/p&gt;
&lt;pre class="literal-block"&gt;&amp;gt;&amp;gt;&amp;gt; print 39.29
39.29&lt;/pre&gt;</description><category>asado</category><category>binario</category><category>decimal</category><category>historia</category><guid>http://blog.taniquetil.com.ar/posts/0292/</guid><pubDate>Fri, 21 Sep 2007 16:48:57 GMT</pubDate></item></channel></rss>