<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Valery C. Briz</title>
    <description>The latest articles on DEV Community by Valery C. Briz (@valerybriz).</description>
    <link>https://dev.to/valerybriz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F213848%2F84c58823-8f3e-4848-8091-c04ac5c81d79.jpeg</url>
      <title>DEV Community: Valery C. Briz</title>
      <link>https://dev.to/valerybriz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/valerybriz"/>
    <language>en</language>
    <item>
      <title>Conseguir tu primer trabajo en Tech 🔥</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Sat, 03 Jun 2023 11:51:43 +0000</pubDate>
      <link>https://dev.to/valerybriz/conseguir-tu-primer-trabajo-en-tech-3c2f</link>
      <guid>https://dev.to/valerybriz/conseguir-tu-primer-trabajo-en-tech-3c2f</guid>
      <description>&lt;p&gt;Hace unos días me invitaron a impartir una charla sobre el proceso para poder conseguir un trabajo en la industria tech a personas que están empezando en el area.&lt;/p&gt;

&lt;p&gt;En la charla me he enfocado en hacer énfasis en los consejos y recomendaciones que a mi misma me han ayudado a lo largo de mi carrera y los recursos que son de mucha utilidad para conseguir un portafolio que destaque sobre los demás.&lt;/p&gt;

&lt;p&gt;Este es el resumen de la presentación con links y tips 🔥 &lt;/p&gt;

&lt;h2&gt;
  
  
  Proceso de selección en tech
&lt;/h2&gt;

&lt;p&gt;El proceso de selección varía entre una empresa/proyecto a otro pero la mayoría de procesos siguen un orden similar al siguiente:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jcln8rx614iwjvnznwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jcln8rx614iwjvnznwi.png" alt="Image description" width="800" height="1264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Currículum vitae
&lt;/h2&gt;

&lt;p&gt;Este primer paso es muy importante por que es la puerta de entrada al proceso de selección y tomando en cuenta que la cantidad de cv's que reciben los reclutadores para posiciones junior son bastante altas, realmente tenemos que sobre salir de entre todos para poder tener una oportunidad.&lt;/p&gt;

&lt;p&gt;En este artículo no me enfocaré en el formato del cv sino mas bien en la sección de experiencias previas.&lt;/p&gt;

&lt;p&gt;Cuando estamos a penas entrando a un area nueva es común que no sepamos que incluir en esta sección, sin embargo hay una gran cantidad de recursos que nos pueden servir para generar experiencias completamente validas para el cv.&lt;/p&gt;

&lt;h4&gt;
  
  
  Contribuír a proyectos de código abierto
&lt;/h4&gt;

&lt;p&gt;Este tipo de experiencia puede aportar bastante solidez a nuestro cv ya que no solo podemos comprobar que hemos desarrollado parte de un proyecto sino que la empresa puede revisar el código que hemos aportado y verificar que es de calidad.&lt;/p&gt;

&lt;p&gt;Las principales plataformas donde podemos encontrar proyectos de código abierto son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com" rel="noopener noreferrer"&gt;https://github.com&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeberg.org" rel="noopener noreferrer"&gt;https://codeberg.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com" rel="noopener noreferrer"&gt;https://gitlab.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A demás esta página recoge un listado de filtros con los cuales podremos encontrar issues o "necesidades" que tienen los proyectos, etiquetados con un nivel "bajo" de experiencia o que son buenos para personas que contribuyen por primera vez:&lt;br&gt;
&lt;a href="https://www.firsttimersonly.com" rel="noopener noreferrer"&gt;https://www.firsttimersonly.com&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hackatones
&lt;/h3&gt;

&lt;p&gt;Los hackatones son eventos en los que un grupo de personas se reunen fisicamente o virtualmente para desarrollar una o varias ideas en un tiempo determinado.&lt;/p&gt;

&lt;p&gt;Estas experiencias también son bastante valoradas porque no solo se trata de desarrollar código sino de desarrollar una idea y de trabajar en equipo. Cualidades muy valoradas al momento de buscar developers.&lt;/p&gt;

&lt;p&gt;Aquí puedes encontrar listados de hackatones que sucederán a lo largo del año:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.eventbrite.es/d/online/hackathon" rel="noopener noreferrer"&gt;https://www.eventbrite.es/d/online/hackathon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackathonspain.com" rel="noopener noreferrer"&gt;https://hackathonspain.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackathon.talent-network.org" rel="noopener noreferrer"&gt;https://hackathon.talent-network.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hackathon.com" rel="noopener noreferrer"&gt;https://www.hackathon.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Competencias y ejercicios
&lt;/h3&gt;

&lt;p&gt;Existen una gran cantidad de sitios donde podemos encontrar ejercicios o ideas de desarrollo de software que podemos desarrollar y subir a nuestro repositorio de preferencia para utilizarlo como portafolio.&lt;/p&gt;

&lt;p&gt;Aquí listo algunas de ellas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/espanol/news/el-desafio-100daysofcode-su-historia-y-por-que-debes-probarlo-para-2022" rel="noopener noreferrer"&gt;https://www.freecodecamp.org/espanol/news/el-desafio-100daysofcode-su-historia-y-por-que-debes-probarlo-para-2022&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/practical-tutorials/project-based-learning" rel="noopener noreferrer"&gt;https://github.com/practical-tutorials/project-based-learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.kaggle.com/competitions" rel="noopener noreferrer"&gt;https://www.kaggle.com/competitions&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;También existen comunidades como &lt;a href="https://hablemospython.dev/" rel="noopener noreferrer"&gt;Hablemos Python&lt;/a&gt; donde se promueve el desarrollo de proyectos realizados por la comunidad y que aportan justamente esa experiencia de desarrollo en equipo para personas de todos los niveles y con conocimientos en distintas tecnologías, ya que la mayoría de proyectos necesitan diversidad de perfiles para poder completarse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entrevista inicial con RH
&lt;/h2&gt;

&lt;p&gt;Una vez que has sido seleccionadx para empezar el proceso de selección, vendrá la primera entrevista con recursos humanos, usualmente querrán conocer un poco sobre tí y sobre tu experiencia previa.&lt;/p&gt;

&lt;p&gt;Aquí es donde utilizaremos todo lo que aprendimos al desarrollar los proyectos anteriores para demostrar los conocimientos con los que contamos.&lt;/p&gt;

&lt;p&gt;Muchas veces en este punto van a preguntarte cual es tu expectativa salarial, aquí podemos tener puntos de vista diferentes, ya que hay personas que prefieren no responder a este tipo de preguntas, lo cual es completamente valido.&lt;/p&gt;

&lt;p&gt;Pero algunas otras personas prefieren establecer una cantidad mínima, por lo que si la empresa no puede pagarte esa cantidad y tu no estas dispuestx a negociarla, el proceso de selección ya no continuaría. Esto puede ser bueno si no quieres invertir tu tiempo en las entrevistas y pruebas técnicas, si al final no se podrá realizar el acuerdo.&lt;/p&gt;

&lt;p&gt;Asi que mi recomendación para este paso es que investigues a la empresa, su valores y sus productos o servicios, para poder saber si es una empresa que encajaría con tu forma de pensar y también para descartar a posibles empresas con culturas laborales tóxicas.&lt;/p&gt;

&lt;p&gt;Un sitio que puede servir para investigar salarios y opiniones es &lt;a href="https://www.glassdoor.es" rel="noopener noreferrer"&gt;https://www.glassdoor.es&lt;/a&gt;, también puedes buscar en linkedin y en plataformas como github. &lt;/p&gt;

&lt;h2&gt;
  
  
  Pruebas técnicas
&lt;/h2&gt;

&lt;p&gt;Existen una gran cantidad de pruebas técnicas, aquí hablaré un poco de los tipos de pruebas a las que me he enfrentado yo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolver un problema con código en tiempo real (ó con límite de tiempo)
&lt;/h3&gt;

&lt;p&gt;En este tipo de prueba lo más importante es entender el problema y explicarle a la persona que entrevista, como planeamos resolverlo, aún a pesar de que el código no funcione.&lt;/p&gt;

&lt;p&gt;Si la posición requiere conocer sobre Testing tendrás que desarrollar con TDD en está prueba.&lt;br&gt;
Algunos sitios donde podras encontrar ejercicios para practicar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://projecteuler.net/archives" rel="noopener noreferrer"&gt;https://projecteuler.net/archives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.hackerrank.com/domains" rel="noopener noreferrer"&gt;https://www.hackerrank.com/domains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://exercism.org" rel="noopener noreferrer"&gt;https://exercism.org&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com" rel="noopener noreferrer"&gt;https://leetcode.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platzi.com/comunidad/retos-de-programacion-para-cualquier-lenguaje-segundo-nivel-condicionales" rel="noopener noreferrer"&gt;https://platzi.com/comunidad/retos-de-programacion-para-cualquier-lenguaje-segundo-nivel-condicionales&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resolver un problema con código de forma asíncrona
&lt;/h3&gt;

&lt;p&gt;En este tipo de prueba nos envían un problema el cual tenemos que resolver y usalmente tendremos algunos días o una semana para hacerlo, con todas las herramientas que tengamos a nuestro alcance. &lt;/p&gt;

&lt;p&gt;Lo más importante en este caso es utilizar buenas prácticas y  si hay código previo en el proyecto, es importante identificar errores o mejoras que se puedan hacer.&lt;/p&gt;

&lt;p&gt;Si después de lograr esto te queda tiempo, has todos los tests que puedas.&lt;/p&gt;

&lt;p&gt;En la entrevista de revisión del código, propón mejoras en el código y si no te dió tiempo de hacer algo, explicales que te hubiese gustado implementar si tuvieras más tiempo.&lt;/p&gt;

&lt;p&gt;Algunos repositorios donde podemos encontrar código de este tipo para practicar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/techops-recsys-lateral-hiring" rel="noopener noreferrer"&gt;https://github.com/techops-recsys-lateral-hiring&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://retosdeprogramacion.com/semanales2023" rel="noopener noreferrer"&gt;https://retosdeprogramacion.com/semanales2023&lt;/a&gt; Respuestas: &lt;a href="https://github.com/mouredev/retos-programacion-2023/tree/main" rel="noopener noreferrer"&gt;https://github.com/mouredev/retos-programacion-2023/tree/main&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pair programming
&lt;/h3&gt;

&lt;p&gt;En este caso es muy importante comunicarte con la persona que te entrevista y preguntarle constantemente su opinión sobre lo que propones ya que ellos te han dicho que es un pair programming y esperan que actues "de forma natural" como si fuese un día normal de trabajo.&lt;/p&gt;

&lt;p&gt;Normalmente se requiere que propongas mejoras al código si es que ya existe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resolver un problema de forma conceptual
&lt;/h3&gt;

&lt;p&gt;En este caso la comunicación es muy importante, explicar con detalle los conceptos que te preguntan y casos de aplicación puede hacer la diferencia.&lt;/p&gt;

&lt;p&gt;No supongas nada, mejor pregunta para estar segurx de que es lo que quieren escuchar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entrevista de cultura laboral
&lt;/h2&gt;

&lt;p&gt;Algunas empresas realizan este tipo de entrevistas donde se trata de entender si tu podrías encajar en el equipo pero también si a tí te hace sentido la empresa. Esta entrevista es muy util para hacer todas las preguntas que tengas sobre el día a día en la empresa y de cuales son las opciones de crecimiento que podrían existir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comunidades
&lt;/h2&gt;

&lt;p&gt;Finalmente algo que siempre le recomiendo a las personas que están en busqueda de trabajo es asistir y formar parte de una o varias comunidades de tecnología.&lt;/p&gt;

&lt;p&gt;Existen comunidades en todo el mundo, algunas tienen actividades en persona y otras actividades virtuales. De cualquier forma, formar parte de una comunidad puede ayudarte a crecer tu red de contactos, aprender de personas que están en distintos niveles en areas similares a la tuya y también para compartir tu experiencia.&lt;/p&gt;

&lt;p&gt;A demás es justo en estas comunidades donde surjen muchos proyectos o eventos en los que es posible participar y que también pueden aportar en tu cv, por ejemplo voluntariados y contribuciones a proyectos open source.&lt;/p&gt;

&lt;p&gt;Muchas de estas comunidades puedes encontrarlas en:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://meetup.es" rel="noopener noreferrer"&gt;https://meetup.es&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://eventbrite.es" rel="noopener noreferrer"&gt;https://eventbrite.es&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;También puedes seguirles en twitter, linkedin y facebook para estar al pendiente de las actividades y noticias de la comunidad.&lt;/p&gt;

&lt;p&gt;¡Espero que estas recomendaciones puedan ayudarte!&lt;/p&gt;

</description>
      <category>trabajo</category>
      <category>frontend</category>
      <category>backend</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Bulk load to Elastic Search with PySpark</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Thu, 01 Jun 2023 14:28:31 +0000</pubDate>
      <link>https://dev.to/valerybriz/bulk-load-to-elastic-search-with-pyspark-2ohj</link>
      <guid>https://dev.to/valerybriz/bulk-load-to-elastic-search-with-pyspark-2ohj</guid>
      <description>&lt;p&gt;If you use Spark to transform your data and you are planning on load it directly from spark to Elastic Search then perhaps this short article is for you.&lt;/p&gt;

&lt;p&gt;Not so long ago I was in the same situation and started reading the &lt;a href="https://www.elastic.co/guide/en/elasticsearch/hadoop/current/spark.html" rel="noopener noreferrer"&gt;Elastic search documentation&lt;/a&gt; to build my PySpark job, but to be honest at the end of my reading I felt like I still had a lot of questions about it. &lt;/p&gt;

&lt;p&gt;So thanks to the help of multiple questions answered in StackOverflow and other forums I was able to implement a PySpark job that actually works.&lt;/p&gt;

&lt;p&gt;That is why I decided to write this small tutorial and to explain a little bit what are the options available.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you want to check the full code then you can find it &lt;a href="https://gist.github.com/valerybriz/a5a69a65df523529dd21498fbfe19dbb" rel="noopener noreferrer"&gt;in this Gist&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connection parameters
&lt;/h2&gt;

&lt;p&gt;The base parameters we need to send in order to connect to Elastic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;org.elasticsearch.spark.sql&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.nodes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;elastic_host&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.port&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;elastic_port&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are using a cloud environment like AWS or Google Cloud you would also need to add the following options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.nodes.wan.only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.nodes.discovery&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Authentication and SSL
&lt;/h2&gt;

&lt;p&gt;This part will depend a little bit on the kind of configurations you currently have on your Elastic Search instance but these are the main options:&lt;/p&gt;

&lt;h3&gt;
  
  
  SSL enabled or disabled:
&lt;/h3&gt;

&lt;p&gt;This option set as &lt;code&gt;true&lt;/code&gt; well enable the ssl for the connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.ssl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Authentication by user name and password:
&lt;/h3&gt;

&lt;p&gt;If you choose to use the authentication by user name and password then these two need to be added.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.http.auth.user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.http.auth.pass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Authentication by ApiKey:
&lt;/h3&gt;

&lt;p&gt;A better way to authenticate is to create an ApiKey and use the Bearer header as an option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;AUTH_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ApiKey &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.http.header.Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AUTH_TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use of a SSL Certificate:
&lt;/h3&gt;

&lt;p&gt;This one can be a little bit tricky since you need to load the &lt;code&gt;.jks&lt;/code&gt; truststore file of your Elastic Search instance to all of the cluster nodes and then add the following options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.ssl.truststore.location&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;truststore_location&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.ssl.truststore.pass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;truststore_pass&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.net.ssl.cert.allow.self.signed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that this trustore_location most be accessible from your Spark application, otherwise it will fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Index resource options
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;WRITE_MODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;append&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# If you want to create the index if it doesn't exists
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.index.auto.index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="c1"&gt;# This is the type of index loading ['update', 'index', 'create'...]
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.write.operation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="c1"&gt;# This is the actual name of the index
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.resource&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;elastic_index&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="c1"&gt;# Mapping for the _id field in Elastic
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.mapping.id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="c1"&gt;# Save all the empty values as null
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;es.field.read.empty.as.null&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;span class="c1"&gt;# The write mode can be 'append' or 'overwrite'
&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;WRITE_MODE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; \
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In general the configurations for the spark elastic loader are self explanatory, we just need to find the correct options for our specific case.&lt;/p&gt;

&lt;p&gt;Hope this can help you!&lt;/p&gt;

</description>
      <category>elasticsearch</category>
      <category>spark</category>
      <category>pyspark</category>
      <category>bigdata</category>
    </item>
    <item>
      <title>3 Data Engineering Pitfalls</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Wed, 07 Jul 2021 16:54:32 +0000</pubDate>
      <link>https://dev.to/valerybriz/5-data-engineering-pitfalls-517m</link>
      <guid>https://dev.to/valerybriz/5-data-engineering-pitfalls-517m</guid>
      <description>&lt;p&gt;Cuando diseñamos o mantenemos una infraestructura de datos hay múltiples pain points que pueden resolverse antes de que sea muy tarde… algunos de ellos son bastante obvios pero quizás no les damos importancia, otros son más difíciles de reconocer, hasta que ya estamos muy dentro y la dificultad para salir de ello es gigantesca. Partiendo de esta base, a lo largo de este artículo les describo tres de las trampas más comunes en ingeniería de datos.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Arquitectura completamente serverless
&lt;/h2&gt;

&lt;p&gt;Antes que nada debo aclarar que en este caso específico me refiero a serverless del tipo AWS Lambda.  ya que actualmente existen una gran cantidad de soluciones efectivas en las distintas clouds que son serverless pero enfocadas a Data workflows como Data flow o AWS Glue.&lt;/p&gt;

&lt;p&gt;Las principales ventajas de los servicios serverless (como Lambda) son el fácil despliegue de la lógica de negocio en un «contenedor» listo para escalar de forma automática y a demás lo barato que puede ser pagar unicamente por el tiempo de ejecución, pero…&lt;/p&gt;

&lt;p&gt;Es justo allí donde está la trampa, porque hasta ahora todas las ventajas que trae consigo serverless suena genial pero que sucede cuando la pequeña lógica de negocio que utilizamos al inicio dentro del serverless empieza a crecer en tamaño y en complejidad?&lt;/p&gt;

&lt;p&gt;Anteriormente mencionamos que el costo de serverless es únicamente por el tiempo de ejecución, pero que sucede si el tiempo de ejecución es tan largo que el servicio casi nunca esta en modo «reposo» o sin consumo de recursos. Y luego claro para poder solventar la complejidad de los pipelines empezamos a crear más y más apps serverless con dependencias entre sí.&lt;/p&gt;

&lt;p&gt;Aunado a todo esto, reintentar la ejecución de un pipeline que ha fallado ya sea parcial o completamente, tomando en cuenta todas estas dependencias es en la mayoría de los casos una tarea manual y muy desgastante.&lt;/p&gt;

&lt;p&gt;¡Boom!&lt;/p&gt;

&lt;p&gt;Sí, boom… cuando se rompe la infraestructura porque es casi imposible mantenerlo a largo plazo a medida que sigue creciendo y solamente queda migrar a una infraestructura más robusta.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Monitoreo
&lt;/h2&gt;

&lt;p&gt;Muchos de ustedes habrán sentido ya esa satisfacción de deployar finalmente la última pieza de su genial pipeline, luego de meses de trabajar en ella y arreglar los errores, finalmente está funcionando y los stakeholders están satisfechos con el servicio que se completó.&lt;/p&gt;

&lt;p&gt;Parece que ya no hay mucho más que hacer acá, hasta que se requieran cambios o agregar características nuevas al servicio.&lt;/p&gt;

&lt;p&gt;¡Cuidado!&lt;/p&gt;

&lt;p&gt;Esta es una trampa que sucede principalmente en proyectos o equipos que están en sus comienzos y tienen demasiado trabajo. Y entonces pensamos que es suficiente con guardar los logs de los distintos procesos y dejamos para después la integración de un verdadero sistema de monitoreo.&lt;/p&gt;

&lt;p&gt;Estrategias para monitoreo hay muchas, lo importante es darles el tiempo adecuado para analizar en que partes del proyecto es crucial tener un monitoreo activo que pueda ayudarnos a prevenir o al menos a identificar rápidamente los errores que posiblemente ocurrirán.&lt;/p&gt;

&lt;p&gt;La mayoría de las veces tardamos mucho más tiempo buscando una solución a un error que montando un sistema de monitoreo que agilizará la solución de estos errores, incluso es muy probable que podamos evitar las consecuencias de un error que puede impactar muchos otros sistemas con tan solo montar alertas adecuadas en el sistema de monitoreo.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Arquitectura de datos sin gobernanza
&lt;/h2&gt;

&lt;p&gt;Aunque el tema de la gobernanza de datos no es algo nuevo, aún se nos hace difícil acostumbrarnos a darle el tiempo necesario a establecer y mantener una gobernanza de datos adecuada.&lt;/p&gt;

&lt;p&gt;Así que empezaremos por identificar si en su infraestructura existe una gobernanza de datos o no.&lt;/p&gt;

&lt;p&gt;Los principales síntomas de una falta de gobernanza son los siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Toda la data cae al mismo bucket o espacio.&lt;/li&gt;
&lt;li&gt;Data de múltiples versiones con estructuras distintas en el mismo espacio.&lt;/li&gt;
&lt;li&gt;No existen reglas o políticas establecidas sobre cómo y dónde guardar la data.&lt;/li&gt;
&lt;li&gt;Los pipelines mezclan workflows que no tienen relación directa en tema o dominio.&lt;/li&gt;
&lt;li&gt;Es difícil hacer modificaciones en los workflows existentes.&lt;/li&gt;
&lt;li&gt;No hay documentación sobre los catálogos de datos.&lt;/li&gt;
&lt;li&gt;No existen entornos (como data lake, data warehouse, etc) específicamente para desarrollo/pruebas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algunas de las consecuencias de la falta de gobernanza son por ejemplo tener una gran cantidad de data duplicada dentro del data lake debido a que la falta de orden hace casi imposible identificar estos duplicados. Cuando hablamos de Big Data esta duplicación puede impactar directamente en los costos no solo de almacenamiento de datos sino también en costos de ejecución ya que mientras más data tengas, más tardan los procesos en transformar y por ende gastan más recursos.&lt;/p&gt;

&lt;p&gt;Gobernanza es el proceso de manejar la disponibilidad, usabilidad, integridad y seguridad de los datos en un sistema, basado en estándares internos y políticas de control de los datos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disponibilidad: Asegurarse de que los datos sean accesibles de una forma fácil y eficiente dependiendo de quien sea el consumidor de estos.&lt;/li&gt;
&lt;li&gt;Usabilidad: Esto implica que los datos resultantes al final del proceso realmente se puedan utilizar para lo que sean necesarios por ejemplo, si son archivos xml o protobufs, poder convertirlos a un formato en el que sea posible consumirlos con queries o por medio de alguna interfáz a la que los consumidores tengan acceso.&lt;/li&gt;
&lt;li&gt;Integridad: Debemos estar seguros de que los datos que obtuvimos están completos y no están sucios.&lt;/li&gt;
&lt;li&gt;Consistencia: Asegurarse de que en caso de haber diferentes versiones o cambios repentinos, por ejemplo al consumir datos desde una fuente externa, esto no debe afectar el actual funcionamiento y pueda existir una transición hacia nuevas versiones.&lt;/li&gt;
&lt;li&gt;Seguridad: No solo mantener los sistemas, conexiones y servers seguros con firewalls, vpns y muchas otras herramientas que tenemos ahora en la nube sino también poder estar seguros de que a pesar de que tengamos un data lake privado, se limite el acceso a datos de producción sensibles a los usuarios que realmente los necesitan y en caso de ser datos muy delicados, tener una estrategia como la encriptación.  También tener la opción de borrar los datos en caso de que un cliente lo pida ya que es su información y que  “el desorden” no sea impedimento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algunas de las estrategias para implementar o mejorar la gobernanza de datos son las siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Establecer políticas de uso de los datos.&lt;/li&gt;
&lt;li&gt;Crear y actualizar los catálogos de datos.&lt;/li&gt;
&lt;li&gt;Crear y actualizar las definiciones/diccionarios de datos.&lt;/li&gt;
&lt;li&gt;Establecer políticas de Seguridad de los datos.&lt;/li&gt;
&lt;li&gt;Reconocer los Data Domains dentro de la organización.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Un Data Domain?&lt;/p&gt;

&lt;p&gt;Es una colección de información y procesos relacionados a esa información que son independientes de otras colecciones o procesos y se consume por medio de su propia interfaz.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;En base a lo comentado, estas son algunas de las conclusiones que he obtenido:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empieza pequeño (Metodología Lean).
Solo puedes controlar lo que puedes medir.
Define quienes son las personas responsables de cada proyecto o dominio.&lt;/li&gt;
&lt;li&gt;La Gobernanza es un trabajo en equipo que requiere de todas las partes involucradas para que pueda funcionar.&lt;/li&gt;
&lt;li&gt;Educa a las personas involucradas en los proyectos para que siempre estén al tanto de las políticas y planificación.&lt;/li&gt;
&lt;li&gt;Mapea y documenta.&lt;/li&gt;
&lt;li&gt;Desarrolla definiciones estandarizadas.&lt;/li&gt;
&lt;li&gt;Identifica los dominios de datos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Originalmente publicado en:&lt;br&gt;
&lt;a href="https://planetachatbot.com/3-trampas-en-ingenieria-de-datos/" rel="noopener noreferrer"&gt;https://planetachatbot.com/3-trampas-en-ingenieria-de-datos/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dataengineering</category>
      <category>datagovernance</category>
      <category>datalake</category>
      <category>data</category>
    </item>
    <item>
      <title>¿Quienes son las PyLadies?</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Sat, 24 Oct 2020 20:21:14 +0000</pubDate>
      <link>https://dev.to/valerybriz/quienes-son-las-pyladies-cb5</link>
      <guid>https://dev.to/valerybriz/quienes-son-las-pyladies-cb5</guid>
      <description>&lt;p&gt;En el marco de las elecciones del Consejo Global (Mundial) de PyLadies, la comunidad del Lenguaje de Programación Python ha tenido un gran movimiento en las redes sociales acerca del tema, por lo que últimamente se acercaron muchas personas a preguntarme de qué se trataban las elecciones y quienes eran PyLadies?&lt;/p&gt;

&lt;p&gt;Cuando yo empecé a organizar meetups sobre el lenguaje Python en Guatemala, lo único que sabía sobre la comunidad era que habían muchos más grupos alrededor del mundo y que no necesitas tener cierto nivel de experiencia para ser organizadora/or de un “capítulo” en tu ciudad, lo más importante es tener el compromiso de liderar la comunidad sin dejarla morir, de ser constante y que lo que te mueve es el simple deseo de aprender y compartir conocimiento con otras personas.&lt;/p&gt;

&lt;p&gt;Las distintas comunidades de Python alrededor del mundo pueden definirse como grupos de personas que se reúnen cada mes a platicar sobre un tema relacionado al lenguaje Python, herramientas, estrategias y vivencias del día a día en el trabajo o el estudio como desarrollador/a de software.&lt;/p&gt;

&lt;p&gt;¿La finalidad? aprender y compartir el conocimiento para que más personas tengan acceso a crecer como desarrolladores/as de software. Para algunas personas puede parecer un poco extraño que alguien quiera compartir conocimiento, tiempo y esfuerzo gratis, pero déjenme decirles que el simple hecho de enseñar, te hace aprender, además de que poder compartir deja una huella imborrable que, al menos en mi caso, le da un sentido muy importante a mi día a día.&lt;/p&gt;

&lt;p&gt;PyLadies se enfoca en crear espacios en los que todas las personas que se identifiquen como chicas puedan sentirse cómodas para compartir y aprender sobre este lenguaje de programación que en los últimos años ha tomado mucho auge.&lt;/p&gt;

&lt;p&gt;Para lograrlo organizamos una gran variedad de actividades como talleres, meetups, congresos, etc. Una de las cosas que más me gustan de PyLadies es que se rige por un código de conducta establecido desde sus comienzos, en el que queda claro que debemos respetar a los demás, de lo contrario la persona que irrespeta no será admitida para asistir en futuras actividades.&lt;/p&gt;

&lt;p&gt;Pero no se refiere únicamente a actitudes extremas de falta de respeto sino también al simple hecho de ser excluyente con personas que tienen menos experiencia en el tema, o a burlarse de los demás, porque en PyLadies pensamos que no existen preguntas tontas y que de hecho la diversidad es muy importante si un equipo o grupo de personas quieren crecer en cualquier ámbito. &lt;/p&gt;

&lt;p&gt;La importancia de comunidades como la de PyLadies en el mundo cada día toma más importancia, cada día crece más y esto en consecuencia genera un aumento de la diversidad en el ámbito estudiantil y laboral, es por ello que un grupo de líderes a nivel mundial de los distintos capítulos de PyLadies se reunieron en 2019 en el evento de PyCon USA y platicaron sobre la necesidad de un Consejo Global que tomara el liderazgo del futuro de PyLadies, con lo cual se realizaron las primeras elecciones para formar el primer Consejo Global.&lt;/p&gt;

&lt;p&gt;Aunque aún queda mucho por definir en los objetivos de este grupo que liderará a PyLadies a nivel mundial, queda claro que es un primer paso certero para que la comunidad siga creciendo y fortaleciéndose en el camino para empoderar a más chicas en el área de tecnología.&lt;/p&gt;

</description>
      <category>pyladies</category>
      <category>python</category>
      <category>community</category>
      <category>comunidad</category>
    </item>
    <item>
      <title>How to Go Serverless like a Pro — Cloud Academy</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Sun, 14 Jun 2020 03:35:12 +0000</pubDate>
      <link>https://dev.to/valerybriz/how-to-go-serverless-like-a-pro-cloud-academy-4knk</link>
      <guid>https://dev.to/valerybriz/how-to-go-serverless-like-a-pro-cloud-academy-4knk</guid>
      <description>&lt;p&gt;Originally posted on &lt;a href="https://cloudacademy.com:443/blog/how-to-go-serverless-like-a-pro/" rel="noopener noreferrer"&gt;cloudacademy.com&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;So, ...no servers? &lt;/p&gt;

&lt;p&gt;Yeah, I checked and there are definitely no servers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well…the cloud service providers do need servers to host and run the code, but we don't have to worry about it. Which operating system to use, how and when to run the instances, the scalability, and all the architecture is managed by the provider. &lt;/p&gt;

&lt;p&gt;But that doesn't mean there's no management at all. It's a common misconception that in a serverless paradigm, we don't have to care about monitoring, testing, securing, and other details that we are used to managing in other paradigms. So let's explore the main characteristics that we need to take in consideration when building a serverless solution.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;First, why serverless?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the great advantages of serverless is that you only pay for what you use. This is commonly known as "zero-scale" which means that when you don't use it, the function can be reduced down to zero replicas so it stops consuming resources — not only network I/O, but also CPU and RAM — and then brought back to the required amount of replicas when it is needed.&lt;/p&gt;

&lt;p&gt;The trigger of a function on an AWS Lambda can be an API gateway event, a modification on a DynamoDB table or even a modification on an S3 file as defined in &lt;a href="https://dashbird.io/blog/what-are-aws-lambda-triggers/" rel="noopener noreferrer"&gt;&lt;em&gt;What Are AWS Lambda Triggers?&lt;/em&gt;&lt;/a&gt;  But to really save money on serverless, you need to take into consideration all of the services that a Lambda needs to work. Serverless architecture provides many advantages, but it also introduces new challenges. In this article, we'll provide best practices when building a serverless solution. &lt;/p&gt;

&lt;p&gt;To deep dive into building, deploying, and managing the serverless framework, check out &lt;a href="https://cloudacademy.com/library/serverless/" rel="noopener noreferrer"&gt;Cloud Academy's Serverless Training Library&lt;/a&gt;. It's loaded with content and hands-on labs to give you the practical experience you need to integrate serverless architecture into your cloud IT environment. &lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring the Lambda
&lt;/h2&gt;

&lt;p&gt;A common mistake is to confuse zero administration with zero monitoring. On a serverless environment, we still need to pay attention to the metrics, and these will be a bit different from the traditional ones like CPU, memory, disk size, etc. Lambda CloudWatch Metrics provides very useful metrics for every deployed function. According &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/monitoring-functions-metrics.html" rel="noopener noreferrer"&gt;to the AWS documentation&lt;/a&gt;, these metrics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invocation Count: Measures the number of times a function is invoked in response to an event or invocation API call.&lt;/li&gt;
&lt;li&gt;Invocation Duration: Measures the elapsed time from when the function code starts executing to when it stops executing.&lt;/li&gt;
&lt;li&gt;Error Count: Measures the number of invocations that failed due to errors in the function (response code 4XX).&lt;/li&gt;
&lt;li&gt;Throttled Count: Measures the number of Lambda function invocation attempts that were throttled due to invocation rates exceeding the customer's concurrent limits (error code 429).&lt;/li&gt;
&lt;li&gt;Iterator Age: Measures the age of the last record for each batch of records processed. Age is the difference between the time the Lambda received the batch, and the time the last record in the batch was written to the stream. This is present only if you use Amazon DynamoDB stream or Kinesis stream.&lt;/li&gt;
&lt;li&gt;DLQ Errors: Shows all the messages that Lambda failed to handle. If the event was configured to be handled by the DLQ, it can be sent again to the Lambda function, generate a notification, or just be removed from the queue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Besides the default metrics, there are plenty of monitoring services like Dashbird, Datadog, and Logz.io that can be integrated, so we can have additional metrics for a better logs visualization.&lt;/p&gt;

&lt;p&gt;Right now, everything seems very clear and straightforward, right? We have some new metrics and configurations to learn, but it is pretty similar to our traditional structures. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But what about tests? Can we even make local tests for serverless?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Local testing
&lt;/h4&gt;

&lt;p&gt;Since we don't manage the infrastructure anymore, can we run it locally? If so, how can we do that?...&lt;/p&gt;

&lt;p&gt;keep reading on &lt;a href="https://cloudacademy.com:443/blog/how-to-go-serverless-like-a-pro/" rel="noopener noreferrer"&gt;cloudacademy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>serverless</category>
      <category>cloud</category>
      <category>testing</category>
    </item>
    <item>
      <title>Django Queries Optimization</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Mon, 30 Mar 2020 00:00:43 +0000</pubDate>
      <link>https://dev.to/valerybriz/django-queries-optimization-10ji</link>
      <guid>https://dev.to/valerybriz/django-queries-optimization-10ji</guid>
      <description>&lt;p&gt;Have you ever asked yourself, is this the best way of doing this query? or is there a more efficient way?&lt;/p&gt;

&lt;p&gt;When we have a project with one or more recurrent or long blocking queries we need to take into big consideration that this query might slow down our application or even make the database crash.&lt;/p&gt;

&lt;p&gt;Some of this times the trick is to use the available options of the ORM and some times the best way is to write a SQL customized query, but how to know what’s the best in each case?&lt;/p&gt;

&lt;p&gt;In this article I’ll show you a series of best practices recommended by Django documentation and by experience so you will have an idea of some of the options out there to optimize your code!&lt;/p&gt;

&lt;p&gt;Before deciding what to use you have to know that you may want to optimize the queries for speed or for memory or both, depending on your requirements. But sometimes optimizing for one will affect the other. Also, the tasks that are processed by the database might not have the same resources cost than those made by a Python process. It is up to you to decide what your priorities are and where the balance must lie so you can improve the server resources according to it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Having the Following Schema
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;UUIDField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;editable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PositiveSmallIntegerField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ForeignKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;on_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PROTECT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;related_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First than nothing you have to understand that Querysets are Lazy, but what does it means?&lt;/p&gt;

&lt;p&gt;It means that the act of creating or declaring a Queryset doesn’t involve any database activity. So you can add filters and conditions line after line and the Queryset won’t be executed until you actually ask for the information, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Filter the users by the name "Ana"
&lt;/span&gt;&lt;span class="n"&gt;user_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age__lte&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Then get only the users where the age is less than 50
&lt;/span&gt;&lt;span class="n"&gt;user_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email__isnull&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# And exclude the users that doesn't have an email
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now in these lines of code, the database gets only one hit in the line print(user_query) which is very useful when you want to add a lot of conditions before the execution but be careful because there are some other methods that might hit the database right away, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Iteration
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Slicing
&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()[:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pickling or Caching
&lt;/span&gt;&lt;span class="n"&gt;pickle_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_queryset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;user_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pickle_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_result_cache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   

&lt;span class="c1"&gt;# Methods like repr(), len(), list(), bool()
&lt;/span&gt; &lt;span class="n"&gt;user_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
 &lt;span class="c1"&gt;# or a boolean condition like:
&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;There is at least one user who&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s name is Ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It also means that you have to distinguish which queries are cached so it won’t hit the database again and which will no matter if the query is repeated for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create the query filtering users with email myemail@gmail.com
&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myemail@gmail.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# Hit the database and retrieve the name value
&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="c1"&gt;# cached version, no database access  
&lt;/span&gt;
&lt;span class="c1"&gt;# Create the query filtering teams named tigers
&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tigers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# query performed
&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# query performed again
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if you need to iterate over a huge dataset and then perform some action with the values a posible solution is to use an iterator().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email__isnull&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
   &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will hit the database just once fetching the matching rows but use iterator() with caution, and make sure that your code is organized to avoid repeated evaluation of the same huge Queryset.&lt;/p&gt;

&lt;p&gt;A way to avoid the excess of memory usage when the dataset is huge is to execute a boolean condition before populating the whole dataset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="c1"&gt;# The first hit to the database confirms if at least one object exists.
&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user_queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
   &lt;span class="c1"&gt;# Another database hit to start fetching the rows in batches.
&lt;/span&gt;   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user_queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iterator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
     &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But don’t abuse of the exists(), count() methods because each time you call them a new hit is performed.&lt;/p&gt;

&lt;p&gt;We also could retrieve everything at once if we know we’ll certainly need it, to do this we can use prefetch_related() or select_related() so we can get the related fields in other objects and the correct object all at once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;prefetch_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return a Queryset that will automatically retrieve, in a single batch, related objects for each of the specified lookups.&lt;/p&gt;

&lt;p&gt;Now you have select_related() that returns a Queryset that will look for the foreign-key relationships, selecting additional related-object data when it executes its query. This is a performance booster which results in a single more complex query but means later use of foreign-key relationships won’t require database queries, for example if you need all the user for the team.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Hits the database
&lt;/span&gt; &lt;span class="n"&gt;team_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tigers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="c1"&gt;# Hits the database again to get the related User objects
&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;team_queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So rather than doing that you can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Hits the database
&lt;/span&gt; &lt;span class="n"&gt;team_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select_related&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tigers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="c1"&gt;# The second line doesn't hit the database, because team_queryset.user  has been previously prepopulated
&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;team_queryset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way to make a query faster is to retrieve individual objects using a unique, indexed column. As in any other ORM, the query will be quicker because of the underlying database index. Also, the query runs much slower when there are multiple objects matching the filter; having a unique constraint on the column guarantees this will never happen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t order results if you don’t care. Sometimes Django orders the dataset even if we didn’t ask for that but we can disable it on a Queryset by calling order_by() with no parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;order_by&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use defer() and only() if  you only need certain fields on a dataset to avoid loading all of the fields. Note that if you do use them later, the ORM will have to go and get them in a separate query, making this a pessimization if you use it inappropriately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This query retrieves all of the rows on the dataset but only the "name"  field
&lt;/span&gt; &lt;span class="n"&gt;user_queryset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Logging All SQL Queries
&lt;/h3&gt;

&lt;p&gt;A pretty useful tool is the ORM logger, this will enable you to inspect all of the queries and also get the time of the execution. To enable this you’ll need to add a few things to your LOGGING configuration in your settings.py. First, you’ll need a handler. The example below logs everything at DEBUG level to the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;LOGGING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
   &lt;/span&gt;&lt;span class="err"&gt;'handlers':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
     &lt;/span&gt;&lt;span class="err"&gt;'console':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
       &lt;/span&gt;&lt;span class="err"&gt;'level':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'DEBUG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
       &lt;/span&gt;&lt;span class="err"&gt;'class':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'logging.StreamHandler'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;  
   &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;  
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you’ll need to add a logger that logs to this handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;LOGGING&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="err"&gt;'loggers':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="err"&gt;'django.db.backends':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;'level':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'DEBUG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;'handlers':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'console'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the above is set up, you should see a stream of SQL queries in your console output every time you hit the database.&lt;br&gt;
Conclusion&lt;/p&gt;

&lt;p&gt;There isn’t a perfect query or a general answer to utilizing the ORM. You should first seek to make your code clear and then work on optimizing it and take into big consideration that some practices may speed up the database processes but spend lots of memory so, be careful and analyze what is the best for your app and your resources.&lt;/p&gt;

&lt;p&gt;Originally posted in &lt;a href="https://icodemag.com/django-queries-optimization/" rel="noopener noreferrer"&gt;https://icodemag.com/django-queries-optimization/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>database</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understanding Python Datetime Handling — Cloud Academy</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Thu, 08 Aug 2019 16:49:31 +0000</pubDate>
      <link>https://dev.to/valerybriz/understanding-python-datetime-handling-cloud-academy-2ob2</link>
      <guid>https://dev.to/valerybriz/understanding-python-datetime-handling-cloud-academy-2ob2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04vs865hd7bat0id4tk6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04vs865hd7bat0id4tk6.jpeg" width="800" height="533"&gt;&lt;/a&gt;Photo by &lt;a href="https://unsplash.com/@aronvisuals?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Aron Visuals&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/time?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Communicating dates and times with another person is pretty simple… right?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“See you at 6 o’clock on Monday”&lt;/em&gt; sounds understandable.&lt;/p&gt;

&lt;p&gt;But was it a.m. or p.m.? And was your friend in the same time zone as you when you said that? When we need to use and store dates and times on Python, we have the same issues — and even more — since we can express a date and time in many ways. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“July 15, 2019 07:05 pm”
“2019-15-07 19:05:53 CDT”
“2019-07-15T23:05:53.256587-05:00”
1563231953
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of these strings and even the integer expresses the exact same date and time, but they all look very different one from another, right? In this article, we’ll discuss Python datetimes best practices to reduce the complexity when using, formatting, and storing datetimes on a daily basis. Here are the highlights of what we’ll cover:&lt;/p&gt;

&lt;p&gt;To dive deeper into the basic fundamentals of Python, check out Cloud Academy’s new &lt;a href="https://cloudacademy.com/learning-paths/python-for-beginners-637/" rel="noopener noreferrer"&gt;Python for Beginners Learning Path&lt;/a&gt;. It’s designed for people new to programming, providing an ideal entry point for people wanting to learn how to program with the Python scripting language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fna7k1xkan7x9w7c586hb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fna7k1xkan7x9w7c586hb.png" width="524" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43rg5i0in5f8m0cbs4v2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43rg5i0in5f8m0cbs4v2.png" width="800" height="1251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Python datetimes best practices
&lt;/h3&gt;

&lt;p&gt;When we talk about a Python datetime format standard, we mean the ISO 8601 (Date and Time Format). This format is used in most of the databases and it has the following structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YYYY-MM-DDThh:mm:ss.sss +00:00

or

YYYY-MM-DDThh:mm:ss.sss TZ
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when we show it to the user, we might want to change the way it looks. This is because if we use a tool to get it from the user — like a calendar or select inputs — it can also vary on the way the data is sent to the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Python parser
&lt;/h3&gt;

&lt;p&gt;Luckily, Python has a parser that understands pretty much all of the cases of a string formatting. For example:&lt;/p&gt;

&lt;p&gt;Using the following libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from dateutil.parser import parse import datetime as dt from dateutil.tz import tzutc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parser will actually recognize parameters like these written as text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;first_date = parse('January 31, 2010') print(type(first_date), first_date)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The type of the object looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt; parse("&amp;lt;class 'datetime.datetime'&amp;gt; 2010-01-31 00:00:00")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the object created looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt; datetime.datetime(2010, 1, 31, 0, 0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parser can also understand standard notations like “Sat” for Saturday:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;second_date = parse("Sat Oct 11 17:13:46 UTC 2003") print(type(second_date), second_date) &amp;gt;&amp;gt; &amp;lt;class 'datetime.datetime'&amp;gt; 2003-10-11 17:13:46+00:00 &amp;gt;&amp;gt; datetime.datetime(2003, 10, 11, 17, 13, 46, tzinfo=tzutc())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also directly create a datetime object without the format as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_new_datetime = dt.datetime(2001, 1, 31, 10, 51, 0) print(my_new_datetime) &amp;gt;&amp;gt; 2001-01-31 10:51:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a Python datetime with a Unix timestamp
&lt;/h3&gt;

&lt;p&gt;There’s yet another way to create a Python datetime with a unix timestamp.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The unix timestamp is a system for describing a point in time. It is the number of seconds that have elapsed since 00:00:00 Thursday, 1 January 1970, Coordinated Universal Time (UTC), minus leap seconds. Every day is treated as if it contains exactly 86400 seconds, so leap seconds are to be subtracted since the epoch. It is used widely in Unix-like and many other operating systems and file formats.&lt;/em&gt; &lt;a href="https://en.wikipedia.org/wiki/Unix_time" rel="noopener noreferrer"&gt;_(Wikipedia, 2019) _&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main characteristic of this format is that we get a datetime stored as an integer. So we can directly convert the Unix timestamp to a Python datetime object with the “fromtimestamp” method as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from_unix_datetime = datetime.datetime.fromtimestamp(528756281) print(from_unix_datetime) &amp;gt;&amp;gt; datetime.datetime(1986, 10, 4, 2, 14, 41)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or backwards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from_datetime_timestamp = dt.datetime.timestamp(from_unix_datetime) print(from_datetime_timestamp) &amp;gt;&amp;gt; 528756281.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting the Python datetime time zone
&lt;/h3&gt;

&lt;p&gt;Now an optional — but important — parameter to include is the time zone of the datetime. The default time zone is UTC or the one set on your project. However, if the datetime is captured at a local time (let’s say central time for example) and the database that stores this information has UTC time, then it will have a difference of five hours. This can create a conflict if the server that retrieves this datetime is on eastern time (ET). If you didn’t set the time zone on the creation, there’s a way to add it after with a as following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_new_datetime.replace(tzinfo=dt.timezone.utc)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or we can set it on the creation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dt.datetime(2001, 1, 31, 10, 51, 0, tzinfo=tzutc())
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another thing to take in consideration is the way you import the datetime library, sometimes on the code we need to call the base datetime library and sometimes we need the datetime.datetime which contains different methods. To avoid this, we can call datetime as dt and datetime.datetime as datetime or to call it directly from dt.datetime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from datetime import datetime import datetime as dt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating datetime ranges
&lt;/h3&gt;

&lt;p&gt;Following with the common Python mistakes, there’s one mistake that happens silently, but it can affect us if we need an exact range of datetimes and our visual calendar tool doesn’t have time selection but only date selection. When we need a datetime range starting from 00:00:00, we can easily add it to the initial date as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;today_datetime = dt.datetime.today() # Create a new datetime with today parameters rounded_date = today_datetime.replace(hour=0, minute=0, second=0, microsecond=0) print(rounded_date) &amp;gt;&amp;gt;2019-07-26 00:00:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also add or subtract time to our datetime with a timedelta. The number of days will initialize a new timedelta with a time of 30 days.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;time_delta = dt.timedelta(days=30) print(dt.datetime.today() + time_delta) &amp;gt;&amp;gt; 2019-08-25 18:46:02.274584
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or compare two datetimes subtracting one from another:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;last_week_day = dt.datetime.today() - dt.timedelta(days=7) print(last_week_day) &amp;gt;&amp;gt; 2019-07-19 18:49:43.580625
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was easy right? Now let’s use an even easier tool to get single datetime parameters:&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting the current date
&lt;/h3&gt;

&lt;p&gt;Get the current day of the month:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_dt = dt.datetime.today() my_dt.day &amp;gt;&amp;gt; 31
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the current day of the week (in this case, it is Friday):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_dt.isoweekday() &amp;gt;&amp;gt; 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the current month of the year (in this case, it is February):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_dt.month &amp;gt;&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the year:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my_dt.year &amp;gt;&amp;gt; 2019
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, an issue that we don’t usually take in consideration: What happens when we set a datetime object as a value on a payload and then we send this as the data of a request?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current_datetime = dt.datetime.today() requests.get(url="http://test_endpoint.com", json={ "date": current_datetime}) &amp;gt;&amp;gt; TypeError: Object of type datetime is not JSON serializable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most of the Python requests libraries won’t accept a datetime, date, or time type object. First, we need to convert it to a string or integer. Since the standard is the ISO 8601 format, we will simply do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;requests.get(url="http://test_endpoint.com", json={"date": current_datetime.isoformat()})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Next steps
&lt;/h3&gt;

&lt;p&gt;Once you have the foundational knowledge of datetimes in Python, it will get a lot more easy to work with. After you learn the basics, you’ll be ready to jump into Cloud Academy’s &lt;a href="https://cloudacademy.com/learning-paths/pythonic-programming-628/" rel="noopener noreferrer"&gt;Pythonic Programming Learning Path.&lt;/a&gt; This learning path will help you master the advanced features of the Python language to ensure your code clean, concise, readable, and maintainable — or “pythonic”.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://cloudacademy.com/blog/understanding-python-datetime-handling/" rel="noopener noreferrer"&gt;&lt;em&gt;https://cloudacademy.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on August 8, 2019.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>datetime</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Web Scraping for Data Scientists (With No Web Programming Background)</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Tue, 06 Aug 2019 16:22:36 +0000</pubDate>
      <link>https://dev.to/valerybriz/web-scraping-for-data-scientists-with-no-web-programming-background-1j3a</link>
      <guid>https://dev.to/valerybriz/web-scraping-for-data-scientists-with-no-web-programming-background-1j3a</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwgytudv774sx63lclyj.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwgytudv774sx63lclyj.jpeg" width="800" height="500"&gt;&lt;/a&gt;Image by Alfons Schüler from &lt;a href="https://pixabay.com/illustrations/background-texture-abstract-scuffed-1418618/" rel="noopener noreferrer"&gt;Pixabay&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;originally posted at:&lt;/em&gt; &lt;a href="https://icodemag.com/web-scraping-for-data-scientists-with-no-web-programming-background/" rel="noopener noreferrer"&gt;&lt;em&gt;https://icodemag.com/web-scraping-for-data-scientists-with-no-web-programming-background/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nowadays data has a very important role in the industry and the need to obtain this data is becoming increasingly high. A big part of this information can be obtained through the internet. Some data is expressed, for example, as comments or hashtags on social networks other can be found as plain texts on web pages and other can be tables at “old” websites with no more format than simple HTML.&lt;/p&gt;

&lt;p&gt;But regardless of the format, what we really care is the information we can obtain from this source, information that we can analyze to learn about our customer for example or increase the amount of data in our database for a further use. Sometimes the sites provide us with the information through APIs or by making available documents that we can easily download, but sometimes there is no other way to obtain it than by inspecting and copying this information directly from the website.&lt;/p&gt;

&lt;p&gt;So far everything is happiness, but what happens when the information we need to obtain is distributed in hundreds or thousands of different pages or routes and is also all messy.&lt;br&gt;&lt;br&gt;
That’s the time when automation of the inspection and extraction of the data comes to the scene!&lt;/p&gt;
&lt;h4&gt;
  
  
  Web Scraping
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Basically scraping is a technique to capture data from a web site and store it into a machine.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We could get the whole code of a web page with a GET request and then manually inspect, order and store it on a database, but Python provides us with some useful solutions to make it easier. One of this options is the Web Crawling Framework &lt;a href="https://scrapy.org/" rel="noopener noreferrer"&gt;Scrapy&lt;/a&gt;. One of it’s main advantages is that it was built on top of &lt;a href="https://twistedmatrix.com/trac/" rel="noopener noreferrer"&gt;Twisted&lt;/a&gt; which makes it asynchronous and faster. In the other hand we have &lt;a href="https://www.crummy.com/software/BeautifulSoup/" rel="noopener noreferrer"&gt;Beautiful Soup&lt;/a&gt; its name comes from the expression “tag soup” which describes a messy and unstructured HTML. We would be using this library since it is vert handy and also helps a lot when the site we are trying to scrape is a real mess (which is a lot of the cases).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.crummy.com/software/BeautifulSoup/" rel="noopener noreferrer"&gt;Beautiful Soup&lt;/a&gt; can get the whole HTML code of the page and store it as an object easier to filter by tags, id’s and DOM’s.&lt;/p&gt;

&lt;p&gt;But first you might not know what a DOM is, so let’s start with a basic HTML class.&lt;/p&gt;

&lt;p&gt;The DOM is a &lt;a href="https://www.w3.org/" rel="noopener noreferrer"&gt;W3C (World Wide Web Consortium)&lt;/a&gt; standard. It’s basically a document object model that can define the properties, methods and events of an HTML element. So a DOM looks like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As said before, on a DOM we can have properties like an &lt;strong&gt;id&lt;/strong&gt; , a &lt;strong&gt;class&lt;/strong&gt; or a &lt;strong&gt;href&lt;/strong&gt; and a really basic HTML page would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Finding HTML Elements by Tag Name&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;”main”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;The DOM is very useful.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This example demonstrates the &lt;span class="nt"&gt;&amp;lt;b&amp;gt;&lt;/span&gt;getElementsByTagName&lt;span class="nt"&gt;&amp;lt;/b&amp;gt;&lt;/span&gt; method.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;”demo”&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;demo&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The DOM is very useful. So for this HTML page the tags or properties would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;id = “main”&lt;/li&gt;
&lt;li&gt;class = “demo”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And our DOM’s would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;html&lt;/li&gt;
&lt;li&gt;body&lt;/li&gt;
&lt;li&gt;h2&lt;/li&gt;
&lt;li&gt;div&lt;/li&gt;
&lt;li&gt;p&lt;/li&gt;
&lt;li&gt;b&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The combination of these DOM’s and its assigned properties would be the ones that will make our search easier.&lt;/p&gt;

&lt;p&gt;If you want to learn a bit more about HTML you can find a lot of information on the &lt;a href="https://www.w3schools.com/html/" rel="noopener noreferrer"&gt;W3Schools&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now we are ready to code!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First we need to install the &lt;a href="https://www.crummy.com/software/BeautifulSoup/" rel="noopener noreferrer"&gt;Beautiful Soup&lt;/a&gt; library and a HTTP requests library in this case wi’ll use  &lt;strong&gt;urlib3&lt;/strong&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;bs4

pip &lt;span class="nb"&gt;install &lt;/span&gt;urllib3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example purposes we’re going to use the following site for the scrape:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;**page\_url = “http://example.webscraping.com/”**&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Before start doing requests to a web page we are going to manually navigate to the &lt;strong&gt;root&lt;/strong&gt; of the site and look for &lt;strong&gt;robots.txt&lt;/strong&gt; (&lt;em&gt;&lt;a href="https://example.webscraping.com/robots.txt" rel="noopener noreferrer"&gt;https://example.webscraping.com/robots.txt&lt;/a&gt;&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;robots.txt&lt;/strong&gt; is a file that every site should have to let bots know which pages are allowed to inspect and which are not. Also it can specify how many requests per second a crawler can do on the site. It is ethical to follow this instructions and not to hit unnecessarily the server while scraping it.&lt;/p&gt;

&lt;p&gt;The first thing we need is to get the whole page source code. It’s recommendable to get it all on a single request, close the connection and then iterate multiple times if needed to find the information we are looking for. It is not only faster but also better for the server we are scraping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;urlib3&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PoolManager&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#instanciate the http requests library
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;\&lt;span class="n"&gt;_url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#make the request to the page
&lt;/span&gt;&lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#store the code as a soup object
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Soup object has all of the page HTML code, so let’s try doing some search. To know what to look for we can do a dynamic inspection on the page making a right click and then select “ &lt;strong&gt;Inspect the Element&lt;/strong&gt; “. Almost all the web browsers has this option. There we can see that the whole block of HTML code containing the first countries has a tag class called &lt;strong&gt;span12&lt;/strong&gt; , now applying that to our code we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;dom_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="n"&gt;tag_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="n"&gt;tag_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;span12&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="n"&gt;span12_object_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dom_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tag_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tag_value&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will return an array containing all the &lt;strong&gt;divs&lt;/strong&gt; found with a &lt;strong&gt;span12&lt;/strong&gt; class and all the children DOMs inside it, which visually would be the flags and the names of the countries.&lt;/p&gt;

&lt;p&gt;If we want to get the link of the images of the flags we can apply the following search to our already filtered “ &lt;strong&gt;div span12&lt;/strong&gt; ” array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;img_dom_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="n"&gt;img_attr_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;div_item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;span12_object_array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;img_object_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;div_item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_dom_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;img_src_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;current_item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_attr_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;current_item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;img_object_array&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;#This is a list comprehension to simply get each found image source url in order
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can print this to see what is every image link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img_src_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally you can store the information to a data base or directly download the images.&lt;/p&gt;

&lt;h4&gt;
  
  
  Insights
&lt;/h4&gt;

&lt;p&gt;A well done scraping won’t cause a problem for the server that stores the information we need, this is important principally for ethical reasons. In the same line we can optimize our code to perform faster operations locally and ask for different information in the future with small changes.&lt;/p&gt;

&lt;p&gt;Also an efficient and reusable code will be easier to maintain and would minimize our code time in the future.&lt;/p&gt;

&lt;p&gt;This is a basic approach to the scraping methods, after understanding this it would be easier to scrape any site even if we find some messy and not ordered HTML code containing the information.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;originally posted at:&lt;/em&gt; &lt;a href="https://icodemag.com/web-scraping-for-data-scientists-with-no-web-programming-background/" rel="noopener noreferrer"&gt;&lt;em&gt;https://icodemag.com/web-scraping-for-data-scientists-with-no-web-programming-background/&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>datamining</category>
      <category>scraping</category>
    </item>
    <item>
      <title>Qué es Blockchain</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Tue, 05 Mar 2019 19:23:46 +0000</pubDate>
      <link>https://dev.to/valerybriz/que-es-blockchain-3a44</link>
      <guid>https://dev.to/valerybriz/que-es-blockchain-3a44</guid>
      <description>&lt;p&gt;Breve introducción a blockchain&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1001%2F0%2AEw4UsuEkKxQOHmrV" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1001%2F0%2AEw4UsuEkKxQOHmrV" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hace un mes comencé a trabajar en &lt;a href="https://www.prescrypto.com/" rel="noopener noreferrer"&gt;Prescrypto&lt;/a&gt;. Dentro de las muchas habilidades y conocimiento que he adquirido, hay uno particularmente que ha llamado mi atención todo este tiempo: la aplicación de &lt;em&gt;Blockchain&lt;/em&gt; en la generación de &lt;a href="https://www.eleconomista.com.mx/tecnologia/Prescrypto-lleva-el-blockchain-a-las-recetas-medicas-electronicas-20170705-0073.html" rel="noopener noreferrer"&gt;recetas electrónicas&lt;/a&gt;. Esta historia empieza varios años antes.&lt;/p&gt;

&lt;h3&gt;
  
  
  En mis primeros años de universidad…
&lt;/h3&gt;

&lt;p&gt;Escuché por primera vez el término &lt;em&gt;Blockchain&lt;/em&gt;. Desde entonces casi siempre lo escuché cuando hablaban de &lt;em&gt;Bitcoin&lt;/em&gt;. Investigando descubrí que era una moneda electrónica pero su procedencia y usabilidad me eran desconocidos, muchos pensaban que se usaba solamente en la &lt;em&gt;deep web&lt;/em&gt;. Con el tiempo aparecieron empresas e instituciones que la adoptaron, lo que puso al alcance del público más información sobre cómo funcionaba ésta nueva tecnología que rompía con los esquemas de transacciones de dinero o datos.&lt;/p&gt;

&lt;p&gt;Para tener más claridad sobre &lt;em&gt;Blockchain&lt;/em&gt;, comencé leyendo sobre conceptos relacionados con la forma cómo se realizaba la minería de &lt;em&gt;Bitcoins&lt;/em&gt;. Ingenuamente creí que ése era el camino, el resultado fue entender que la minería es únicamente una parte del todo. Apenas había logrado comprender una pieza del rompecabezas de muchas más piezas de las que imaginé al inicio. Después de muchas lecturas, conversaciones y meditaciones, logré juntar las partes y entender mejor a qué refería el concepto de la tecnología &lt;em&gt;Blockchain&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Varios años después…
&lt;/h3&gt;

&lt;p&gt;Llegué a &lt;a href="https://www.prescrypto.com/" rel="noopener noreferrer"&gt;Prescrypto&lt;/a&gt; con un concepto más claro sobre este tipo de tecnología y su funcionamiento. Y el conocimiento que me compartió el equipo y las experiencias que viví durante el primer mes de trabajo me ayudaron, ¡finalmente!, a comprender cómo funciona &lt;em&gt;Blockchain&lt;/em&gt; como un todo. Así como que el uso de esta tecnología, fuera de los sistemas de transacciones monetarias -como originalmente inició-, es muy amplio pues al integrarla en otros procesos puede resolver muchas situaciones complejas relacionadas con la transmisión de información.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reto: ¿de qué se trata mi trabajo?
&lt;/h3&gt;

&lt;p&gt;Pregunta recurrente cuando platico con mi familia y amigos. Explicarles de qué se trata mi trabajo es un reto que siempre empieza con cinco palabras: &lt;em&gt;¿has escuchado hablar sobre Bitcoin?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sí&lt;/em&gt; es la respuesta usual. Me sorprende que conozcan el término sin importar la edad o el área en la que se desenvuelven. Sin embargo, la noción que la mayoría tiene suele ser vaga. Ante eso, decidí idear una forma de explicar de manera concreta y general qué es &lt;em&gt;Blockchain&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Después de varias pruebas con diferentes conejillos de indias, el resultado fue que ya no me ven con cara de susto al finalizar mi explicación. Tampoco me enredo tanto ni doy detalles que puedan confundirlos. Les hablaré de esta tecnología porque la utilizo todo el tiempo en mi &lt;a href="http://blog.prescrypto.com/2018/02/23/como-funcionan-las-recetas-electronicas/" rel="noopener noreferrer"&gt;trabajo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es Blockchain?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Blockchain&lt;/em&gt; se traduce al español como “cadena de bloques”, y cada uno de ellos contiene información. Esta tecnología es utilizada en la transmisión y almacenamiento de datos que se encriptan para garantizar su seguridad. Esto quiere decir que ellos cambian a una forma de texto incomprensible a simple vista protegiéndose de miradas ajenas.&lt;/p&gt;

&lt;p&gt;Ya que un paquete de información o datos es encriptado, éste se convierte en un bloque que es unido, en cadena, a otro. La unión hace que entre ellos compartan información, como la posición en la que están respecto a los otros bloques. Imaginemos que la información encriptada es literalmente una pieza con forma única como la siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F214%2F0%2AMhRXTkAW_NpNrNcE" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F214%2F0%2AMhRXTkAW_NpNrNcE" width="214" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si a la nueva pieza le agregamos la información sobre la pieza anterior, la nueva se modificará un poco para poder encajar perfectamente con la anterior:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F292%2F0%2AfRhKK3yPIntSRg_c" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F292%2F0%2AfRhKK3yPIntSRg_c" width="292" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pieza a pieza, o bloque a bloque, se va armando una cadena de información encriptada. Un bloque nuevo siempre será añadido al final de la cadena, no en otro lugar de ésta. Cuando un nuevo bloque es ingresado a una cadena se genera una llave única que servirá para desencriptar solamente la información de ese bloque, este proceso es conocido como &lt;em&gt;minar&lt;/em&gt; y lo realiza un tercero que no tiene conocimiento de la información contenida en el bloque. La llave generada sólo es conocida por el usuario que añade el bloque a la cadena. La cadena puede recorrerse pieza por pieza hasta llegar a la que necesitamos. Tanto la cadena como cada pieza son inmutables, lo que quiere decir que no pueden ser cambiadas o borradas una vez que se forman.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F254%2F0%2ApARVExuYqnZjqNxO" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F254%2F0%2ApARVExuYqnZjqNxO" width="254" height="159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Es posible cambiar alguno de los bloques?
&lt;/h3&gt;

&lt;p&gt;Para agregar un bloque a la cadena éste debe contener información del bloque al que se une, esto provoca que el nuevo bloque cambie su forma original y tenga una nueva que encaje perfectamente con el último bloque de la cadena. ¿Lo recuerdan, cierto? Si un bloque es alterado, la información encriptada cambia, lo que provoca que ya no encaje con el bloque anterior.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F281%2F0%2ABqIaxsd0ijAi_r_s" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F281%2F0%2ABqIaxsd0ijAi_r_s" width="281" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y así sucesivamente cada pieza quedará alterada causando que toda la cadena tenga un error que podrá ser detectado inmediatamente como una alteración fuera de lo normal en la cadena. A continuación podemos la cadena original arriba y abajo la cadena alterada en la pieza azul:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F371%2F0%2AXKIZu-vD_ZmAP3oQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F371%2F0%2AXKIZu-vD_ZmAP3oQ" width="371" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es un sistema distribuido?
&lt;/h3&gt;

&lt;p&gt;Esta forma de unir y formar cadenas de información encriptada garantizan la seguridad en la transmisión de datos. Otra muy importante es que &lt;em&gt;Blockchain&lt;/em&gt; es un sistema distribuido. Esto quiere decir que la copia exacta de una cadena está guardada simultáneamente en más de un sitio sin que exista un master, o fuente original, en específico. Cada uno de estos sitios puede comprobar la fiabilidad de la cadena y de cada pieza nueva que ingresa a la misma.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F523%2F0%2AKj7pA5PQww8SDfv-" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F523%2F0%2AKj7pA5PQww8SDfv-" width="523" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si hubiese una alteración en algún bloque, como en el ejemplo del bloque azul, y ésta haría cambiar la cadena completa para que todos los bloques volviesen a encajar correctamente. Esto sería complicado porque tendría que ocurrir simultáneamente en cada uno de los sitios donde la cadena está guardada.&lt;/p&gt;

&lt;p&gt;Por si fuera poco, si un usuario quiere obtener la información de una de estas piezas debe de desencriptarla con la llave (única) que se generó al unir el bloque a la cadena. No está de más decir que esta llave únicamente servirá para esa pieza ya que cada una tiene su propia llave.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blockchain es…
&lt;/h3&gt;

&lt;p&gt;Como pueden ver, &lt;em&gt;Blockchain&lt;/em&gt; es un sistema muy seguro de guardar información sensible pero debido a su forma de ordenar la información y hacerla fácilmente rastreable (media vez se cuente con los accesos necesarios) también puede ser útil en casos en los que se debe guardar información interconectada de forma compleja, aunque esta información no sea necesariamente sensible.&lt;/p&gt;

&lt;p&gt;Espero que esta explicación general pero concreta ayude a comprender de qué se trata &lt;em&gt;Blockchain&lt;/em&gt; o, si ya era claro el concepto pero no cómo explicarlo, ahora sea más fácil hacerlo.&lt;/p&gt;

&lt;p&gt;Originalmente publicado en &lt;a href="http://blog.prescrypto.com/2018/08/04/mi-primer-mes-en-prescrypto/" rel="noopener noreferrer"&gt;http://blog.prescrypto.com/2018/08/04/mi-primer-mes-en-prescrypto/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Reactive Programming in Python-Auth0</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Fri, 26 Jan 2018 22:02:20 +0000</pubDate>
      <link>https://dev.to/valerybriz/reactive-programming-in-python-1hkp</link>
      <guid>https://dev.to/valerybriz/reactive-programming-in-python-1hkp</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W2km4y49--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/460/1%2AP4nLyOPjf0MmVt-YEjKxyw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W2km4y49--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/460/1%2AP4nLyOPjf0MmVt-YEjKxyw.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Reactive Programming?
&lt;/h3&gt;

&lt;p&gt;In a way, reactive programming isn’t a new thing. Our typical click events are an asynchronous data stream which we can observe and trigger actions from it. That’s how it works, but Reactive Programming makes things so much easier by adding a toolbox of operators to filter, create, transform, and unify any of those streams. In just a few lines of maintainable code, we can have web sockets that receive multiple requests and handle them on an asynchronous process that serves a filtered output.&lt;/p&gt;

&lt;p&gt;Web applications contain lots of database operations, network calls, nested callbacks, and other computationally expensive tasks that might take a long time to complete (or even block other threads until it’s done). This is where Reactive Programming enters, it gives us the facility to convert almost anything to streams (like variables, properties, user inputs, caches, etc) to manage it asynchronously. Besides that, it also gives us an easy way to handle errors. A task that is usually hard task within asynchronous programming. Reactive Programming makes our code more flexible, readable, maintainable, and easy to write.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Does Reactive Programming Really Means?
&lt;/h3&gt;

&lt;p&gt;The main difference between &lt;a href="https://en.wikipedia.org/wiki/Event-driven_programming"&gt;Event-Driven programming&lt;/a&gt; and Reactive Programming is the real trigger of the action. While the Event-Driven programming focuses on handling any event (such as a button click) to trigger the corresponding action, Reactive Programming wraps data into the reactive system as events. This enables us to do things like listening to user inputs as events that trigger actions only if the input changed from the previous one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Reactive, in Reactive Programming, means a dynamic reaction to change in streams.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reactive Programming is a programming paradigm oriented around data flows and the propagation of change. This means that, when a data flow is emitted by one component, the Reactive Programming library will automatically propagate those changes to other components until it reaches the final receiver.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does Reactive Programming Works?
&lt;/h3&gt;

&lt;p&gt;Let’s take into consideration &lt;a href="http://reactivex.io/"&gt;ReactiveX&lt;/a&gt;, the most famous implementation of the Reactive Programming paradigm. ReactiveX is mainly based on two classes: the Observable and Observer classes. The Observable class is the source of data streams or events and the Observer class is the one that consumes (or reacts to) the emitted elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observables in Reactive Programming
&lt;/h3&gt;

&lt;p&gt;An Observable packs the incoming data so it can be passed from one thread to another. The Observable can be configured so it regulates when to supply data. For example, it could be triggered periodically or only once in their life cycle. There are also various functions that can be used to filter or transform the observable so the observer only emits certain data. All this is used instead of callbacks, which means that our code becomes more readable and less fallible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rx import Observable, Observer 

source = Observable.from_list([1,2,3,4,5,6])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It’s common to use Observables in a way that it doesn’t give data until some Observer subscribes to it. Known as &lt;a href="https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_need"&gt;"call by need"&lt;/a&gt;, this is an evaluation strategy which delays the evaluation of an event until its value is needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observers in Reactive Programming
&lt;/h3&gt;

&lt;p&gt;The Observer consumes the data stream emitted by the Observable. An Observable can have multiple Observers so each data item emitted will be received by each Observer. The "listening" to the stream is called subscribing. Observers subscribe to the Observable with the subscribe() method to receive the emitted data.&lt;/p&gt;

&lt;p&gt;The Observer can receive three types of events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;on_next()&lt;/strong&gt;: when there is an element in the data stream;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;on_completed()&lt;/strong&gt;: when no more items are coming, it implies end of emission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;on_error()&lt;/strong&gt;: when there is an error thrown from the Observable (it also implies end of emission);
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class PrintObserver(Observer): 
    def on_next(self, value): 
        print("Received {0}".format(value)) 
    def on_completed(self):     
        print("Done!") 
    def on_error(self, error): 
        print("Error Occurred: {0}".format(error)) 

source.subscribe(PrintObserver())
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We don’t have to specify all three event types in the code. We can choose which events to observe using the named arguments, or simply providing a lambda for the on_next function. Typically, in production, we will want to provide an on_error handler so errors are explicitly handled by the subscriber.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source = Observable.from_list([1,2,3,4,5,6]) 
source.subscribe(lambda value: print("Received {0}".format(value)))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Subjects in Reactive Programming
&lt;/h3&gt;

&lt;p&gt;The Subject is the Observable extension that simultaneously implements the Observer interface. That is, Subjects acts like both Observers and Observables. They receive messages about events (like Observers) and notify their subscribers (like Observables). This implies two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can subscribe to a Subject, just like an Observ­able.&lt;/li&gt;
&lt;li&gt;A Sub­ject can sub­scribe to other Observables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, the main dif­fer­ence between a Sub­ject and an Observable is that all of the Sub­ject subscribers share the same action. This means that, when a Sub­ject pro­duces data, all of its sub­scribers will receive the same data. This is unlike Observ­ables, where each sub­scrip­tion causes an inde­pen­dent exe­cu­tion of the observable.&lt;/p&gt;

&lt;p&gt;A Subscriber can not only subscribe to an Observable but also unsubscribe from it. It is important to remember to unsubscribe from the asynchronous calls. When calling unsubscribe(), all the operators unsubscribe from one another in sequence from top to bottom. So we can avoid memory leaks. In the case of the Subjects, we will use the dispose method which can be thought of as the subscription itself, or perhaps a token representing the subscription. Disposing it will dispose the subscription and also unsubscribe. The unsubscribe call can be placed in the socket on_close() method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def on_close(self): 
    self.combine_latest_sbs.dispose() 
    print("WebSocket closed")
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Continue reading this Article at &lt;a href="https://auth0.com/blog/reactive-programming-in-python/"&gt;Auth0.com&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://auth0.com/blog/reactive-programming-in-python/"&gt;&lt;em&gt;auth0.com&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>functionalprogrammi</category>
      <category>python</category>
      <category>asynchronous</category>
      <category>reactiveprogramming</category>
    </item>
    <item>
      <title>Desarrollando un Chatbot Básico en 10 minutos</title>
      <dc:creator>Valery C. Briz</dc:creator>
      <pubDate>Tue, 26 Sep 2017 07:53:45 +0000</pubDate>
      <link>https://dev.to/valerybriz/desarrollando-un-chatbot-basico-en-10-minutos-4g7p</link>
      <guid>https://dev.to/valerybriz/desarrollando-un-chatbot-basico-en-10-minutos-4g7p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffj6lo60tym6evmti60sq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffj6lo60tym6evmti60sq.jpeg" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Te interesan los ChatBots? No sabes por donde empezar?
&lt;/h3&gt;

&lt;p&gt;A veces la mejor forma de empezar es intentandolo, algo simple y funcional que en el mismo desarrollo te vaya enseñando y a la vez dando ideas sobre lo que podrías conseguir despues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Asi que aquí vamos!
&lt;/h3&gt;

&lt;p&gt;Para este tutorial vamos a utilizar Telegram como plataforma para nuestro chatbot y Python como lenguaje de desarrollo para poder lograr nuestro objetivo rapido y sin tanto esfuerzo.&lt;/p&gt;

&lt;p&gt;Ok primero necesitamos un Token para utilizar nuestro bot, para eso nos vamos a Telegram y buscamo al “BotFather”, le enviamos el comando /newbot&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61ww79b6em5bk6fn53ps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61ww79b6em5bk6fn53ps.png" width="515" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Entonces preguntará cuál es el nombre del Bot y cual es el ID (hay que tomar en cuenta que el ID/Username del bot no se puede repetir, por lo que hay que escoger un ID único, usualmente al final lleva la palabra Bot), en la última pregunta nos respondera con el Token y un Url para ir a la conversacion con nuestro bot.&lt;/p&gt;

&lt;p&gt;El Token se mira algo asi como esto: &lt;strong&gt;123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11&lt;/strong&gt; , de ahora en adelante simplemente usaremos &lt;strong&gt;&lt;/strong&gt; para referirnos a ello.&lt;/p&gt;

&lt;p&gt;Ahora copia el Token y pegalo en algún lugar seguro, proximamente vamos a utilizarlo.&lt;/p&gt;

&lt;p&gt;Si aún no tienes Python instalado puedes ir a &lt;a href="https://www.python.org/" rel="noopener noreferrer"&gt;https://www.python.org/&lt;/a&gt; para descargarlo e instalarlo.&lt;/p&gt;

&lt;p&gt;En el medio hay una gran cantidad de APIs utiles para Python y Telegram-Bots, si quieres saber un poco mas sobre ello puedes ir a:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/python-telegram-bot/python-telegram-bot" rel="noopener noreferrer"&gt;https://github.com/python-telegram-bot/python-telegram-bot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esta ocasión vamos a utilizar este API que es bastante completo y facil de usar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/datamachine/twx.botapi" rel="noopener noreferrer"&gt;https://github.com/datamachine/twx.botapi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Primero lo instalamos por medio de pip.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install twx.botapi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, Necesitamos un API que nos diga el clima en la ubicación que solicitaremos, para ello utilizaremos Open Weather Map:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/csparpa/pyowm" rel="noopener noreferrer"&gt;https://github.com/csparpa/pyowm&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pyowm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y para utilizarlo es necesario un API KEY que puedes obtener aquí:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://openweathermap.org/appid" rel="noopener noreferrer"&gt;http://openweathermap.org/appid&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De ahora en adelante nos referiremos al api key como &lt;strong&gt;&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Este API nos proporciona datos como nubosidad, viento, temperatura y algunos otros detalles acerca del clima en la ubicación que le enviemos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Perfecto! estamos listos para desarrollarlo!
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# -\*- coding: utf-8 -\*-
#python2.7
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sleep&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;twx.botapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TelegramBot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ReplyKeyboardMarkup&lt;/span&gt; &lt;span class="c1"&gt;#Telegram Bot API
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;traceback&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pyowm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OWM&lt;/span&gt; &lt;span class="c1"&gt;#API del Clima
&lt;/span&gt;
&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
Inicializamos nuestro Bot y el API del Clima
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="n"&gt;TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;OWMKEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;OWMKEY&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;bot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TelegramBot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_bot_info&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#Esperamos por un mensaje entrante
&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt; 
&lt;span class="n"&gt;last_update_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; 
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#Este es el procedimiento que se ejecuta al llegar un mensaje 
&lt;/span&gt;    &lt;span class="c1"&gt;#Vamos a utilizar un Teclado customizado 
&lt;/span&gt;    &lt;span class="n"&gt;keyboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Get Weather&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="c1"&gt;#Al teclado le agregaremos un Boton de Obtener el clima 
&lt;/span&gt;    &lt;span class="n"&gt;reply_markup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReplyKeyboardMarkup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyboard&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#Aqui creamos el teclado 
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#Si el mensaje tiene un chatID y un contenido de texto entonces lo identificamos como texto
&lt;/span&gt;        &lt;span class="n"&gt;chat_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; 
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;
        &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; 
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;chat_id&lt;/span&gt; 
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; 
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Get Weather&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#Si el usuario esta enviando el comando correcto para obtener el clima entonces preguntamos su ubicación 
&lt;/span&gt;            &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;please send me your location&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
            &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;please select an option&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reply_markup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reply_markup&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#Si no contiene el comando entonces mostramos las opciones de nuevo
&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#Si el mensaje contiene una ubicación entonces generamos el clima en ese sitio 
&lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt; 
        &lt;span class="n"&gt;chat_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; 
        &lt;span class="n"&gt;owm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OWM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OWMKEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#inicializamos el API del clima
&lt;/span&gt;        &lt;span class="n"&gt;obs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;owm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;weather_at_coords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#creamos un observation 
&lt;/span&gt;        &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#creamos un objeto Weather como w 
&lt;/span&gt;        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# &amp;lt;Weather - reference time=2013-12-18 09:20, status=Clouds&amp;gt; 
&lt;/span&gt;        &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_location&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# creamos una ubicacion respecto al objeto weather 
&lt;/span&gt;        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_detailed_status&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
        &lt;span class="n"&gt;placename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_name&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
        &lt;span class="n"&gt;wtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_reference_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeformat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;iso&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_temperature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;celsius&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;temp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Weather Status: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; At &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;placename&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;wtime&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; Temperature: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#Enviamos la respuesta con el clima
&lt;/span&gt;        &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;please select an option&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reply_markup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reply_markup&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#enviamos de nuevo el teclado para que lo muestre en pantalla
&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;please select an option&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reply_markup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;reply_markup&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#Este loop sirve para esperar por los mensajes entrantes
&lt;/span&gt;    &lt;span class="n"&gt;updates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_updates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;last_update_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;#esperamos y obtenemos el mensaje
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;updates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;#obtenemos los datos del mensaje
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_update_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;#si el mensaje que estamos recibiendo es nuevo entonces, procesarlo
&lt;/span&gt;                &lt;span class="n"&gt;last_update_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_id&lt;/span&gt; 
                &lt;span class="nf"&gt;process_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#lo enviamos a la función que lo procesa 
&lt;/span&gt;                &lt;span class="k"&gt;continue&lt;/span&gt; 
        &lt;span class="k"&gt;continue&lt;/span&gt; 
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="n"&gt;ex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; 
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;traceback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format_exc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
        &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora podemos guardarlo y ejecutarlo&lt;/p&gt;

&lt;p&gt;Si todo fue correctamente entonces obtendras algo como esto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e0l6o6jztoditk707zf.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e0l6o6jztoditk707zf.jpeg" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Genial! ahora es momento de que leas un poco mas y agregues algunas imagenes e interacción al bot, &lt;strong&gt;pero por ahora tenemos nuestro nuevo y reluciente BOT funcionando y siendo util!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si quieres saber un poco más sobre este API para bots de telegram puedes ir a la página de la documentación en:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pythonhosted.org/twx/twx/botapi/botapi.html" rel="noopener noreferrer"&gt;https://pythonhosted.org/twx/twx/botapi/botapi.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;También aqui puedes encontrar algunos ejemplos del API del clima:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/csparpa/pyowm/blob/master/pyowm/docs/usage-examples.md" rel="noopener noreferrer"&gt;https://github.com/csparpa/pyowm/blob/master/pyowm/docs/usage-examples.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Espero te sea util!&lt;/p&gt;




</description>
      <category>tech</category>
      <category>chatbots</category>
      <category>weather</category>
      <category>python</category>
    </item>
  </channel>
</rss>
