Dabbling with Python again

My relationship with Python is a coming-and-going one. I was recently chatting with Oliver and he asked me what I didn’t like of Python and I said the answer was subjective, but didn’t have an otherwise straight, concise, informed answer. It’s more about feeling, actually. I want to have a better answer.

I currently prefer Ruby to Python, but I want to like Python. I’m not interested on finding out which one is better or picking a winner, I want to be fluent on both languages and use whichever does the best job for the task. I wouldn’t rewrite my Ruby xdotool wrapper in Python, for example. And I wouldn’t rewrite my code generator written in PHP because PHP is something Python and Ruby are not: a templating language. Best tool for the job.

While I can do (and have done) stuff with Python, I don’t consider myself a good Python programmer. There’s lots of gaps in my knowledge. I don’t feel comfortable with it. There goes that feel thing again, dargh. Whatever, I just want to learn Python properly.

I rewrote my latest Ruby script to Python, it automates getting the day’s Zoom invitation for sending it to my church’s WhatsApp group. Surely there’s better, pythonic ways of doing things, but it works and it gave me a better understanding on how to do things in Python based on how I usually write them in Ruby.

And I learnt about assignment expressions. I didn’t know Python couldn’t do that and I’m glad they added them to the language already. The reason behind them was exactly what I stumbled with: having a condition where a regular expression matches and needing the match object assigned to a variable. I was like, “why can’t I assign in a condition?”

Trying xdotool and pyautogui

I tried xdotool and it’s pretty cool. I was automating setting up my Slack status. It finds the Slack window, focuses it, clicks here and there and — tah-dah! — my status is updated. It totally depends on things being in fixed places, but it works.

Then I tried pyautogui planning to port this script and see how it compares with xdotool, but I was surprised right from the start to discover pyautogui doesn’t have any feature to find or operate on windows. So I’ve decided to stick with xdotool and dive deeper. I might try pyautogui some other time.

One thing I liked about pyautogui is it’s “failsafe” — if you slam the mouse and move the cursor to any screen corner, pyautogui will stop running. This is a great feature. One automation of mine with xdotool didn’t quite work (the popup appeared too late) and suddenly xdotool was blindly doing stuff on the wrong places and I couldn’t stop it. No damage was done, but it was scary.

I totally needed something like pyautogui’s, but this required a higher-level language. I went with Ruby. My failsafe is the top or bottom edge of the screen. Before it executes any xdotool command it checks the mouse location and throws an exception. Works pretty well and I recurred to it when I made a mistake and the automation misbehaved.

Lesson learnt: automating the GUI is powerful, but also dangerous. Unlike a shell script, the GUI is an unpredictable environment and things can quickly derail. I like the way pyautogui’s documentation describes this:

Like the enchanted brooms from the Sorcerer’s Apprentice programmed to keep filling (and then overfilling) the bath with water, a bug in your program could make it go out of control. It’s hard to use the mouse to close a program if the mouse cursor is moving around on its own.

It’s a powerful, but double-edged sword. And lots of fun too! Automating the GUI is another dimension and a very useful skill to have.

Cambiando a nodenv

Hace como dos años atrás necesité usar una versión específica de Node para un cliente. Lo primero que encontré fue nvm, así que eso estuve usando.

Ayer quise iniciar un proyecto usando otra versión específica y me sorprendió descubrir que nvm no cambia automáticamente de versión como rbenv. Con rbenv puedes definir que un proyecto use cierta versión específica de Ruby y lo guarda en un fichero que puedes subirlo al repositorio de Git.

nvm no hace nada automáticamente. Ni siquiera si creas un fichero .nvmrc — tienes que ejecutar un comando para que lea la versión que están en este fichero.

Sorprendido, busqué otra alternativa y encontré nodenv, que es un fork de rbenv, la interface es idéntica y cambia de versiones automáticamente. Altamente recomendado.

Complicación innecesaria

Los feeds RSS de Drawr (un website de dibujo japonés) muestran sus imágenes reducidas a 500 pixels, pero yo quería verlos con las imágenes a tamaño completo.

Luego de escribir gran parte de un script usando Ruby, Mechanize y Nokogiri, me topé con el problema que el feed está mal formado y eso no le gusta a Nokogiri. Pensé en usar expresiones regulares, como en los viejos tiempos, para sacar los datos de cada item y me comenzó a tomar más tiempo.

Tras analizar el problema nuevamente, me di cuenta que estaba tratando de resolverlo de la manera más complicada posible: hacer parse del feed RSS y armar uno nuevo sólo para cambiar la URL de la imagen, de “imagen_500.jpg” a “imagen.jpg”.

La solución, quizás ya obvia para ustedes, fue tomar el feed RSS como una gran cadena de texto y hacer un search and replace para eliminar la cadena “_500”. Listo. En menos de un minuto. Creo que me estoy oxidando.

Descargando trailers de Filmtrailer

Filmtrailer era uno de los podcasts de iTunes a los que estuve suscrito. La teoría es que iTunes descarga los podcasts automáticamente y los tiene listos para sincronizarlos al iPhone.

En la práctica me topé con varios detalles. No puedes decirle a iTunes una hora específica cuándo descargar y lo hacía en horario de trabajo, mi iPhone de 8Gb se llenaba rápidamente, la sincronización era lenta, iTunes es lento, etc.

Recientemente recordé Filmtrailer y como ya no quiero usar iTunes, hice un script de Ruby que descarga nuevos trailers de la misma fuente. Una tarea de cron lo ejecuta a las cuatro de la mañana.

Pueden descargar el script aquí. Requiere wget y las gemas Mechanize y Nokogiri. En realidad podría reemplazarse Mechanize con open-uri, pero lo programé sobre la base de un script anterior más complicado y quedó así.

RubyMotion: Ruby for iOS

¡Qué noticia tan emocionante! RubyMotion te permite crear aplicaciones para iOS (iPhone, iPad) usando Ruby. Tienes acceso a todas las APIs, es compilado (el ejecutable es veloz, veloz), hay una REPL alucinante y todo sobre la línea de comandos. Esto es del mismo desarrollador de MacRuby, garantía de un producto sólido.

Por el momento miro de lejos la posibilidad de hacer desarrollos para iOS, pero si algún día me animo, de hecho incluyo en el presupuesto una licencia.

Aprendiendo Ruby con Ruby Koans

Ruby Koans es un método muy original para aprender a programar en Ruby.

The Koans walk you along the path to enlightenment in order to learn Ruby. The goal is to learn the Ruby language, syntax, structure, and some common functions and libraries. We also teach you culture. Testing is not just something we pay lip service to, but something we live. It is essential in your quest to learn and do great things in the language.