Hernán Grecco: PyVISA command-line utilities


PyVISA is a Python frontend for the VISA library that enables controlling all kinds of measurement equipment through GPIB, RS232, USB and Ethernet among others interfaces.

If you are following the development of PyVISA you might have seen that we have recently made the visa module executable to provide a few useful utilities. To try this, you need to update to the latest PyVISA:

$ pip install -U https://github.com/hgrecco/pyvisa/zipball/master

First, we now provide a simpler way to get debug information:

$ python -m visa info
Machine Details:
   Platform ID:    Darwin-10.8.0-x86_64-i386-32bit
   Processor:      i386

   Implementation: CPython
   Executable:     /Users/grecco/envs/lantz/bin/python
   Version:        3.2.3
   Compiler:       GCC 4.2.1 (Apple Inc. build 5666) (dot 3)
   Bits:           32bit
   Build:          Apr 10 2012 11:25:50 (#v3.2.3:3d0686d90f55)
   Unicode:        UCS2

PyVISA Version: 1.6.1

      Version: 1.6.1 (bundled with PyVISA)
      #1: /Library/Frameworks/visa.framework/visa:
         found by: auto
         bitness: 32
         Vendor: National Instruments
         Impl. Version: 5243392
         Spec. Version: 5243136
      Version: 0.1.dev0
      ASRL INSTR: Available via PySerial (10.8.0)
      TCPIP INSTR: Available
      USB INSTR: Available via PyUSB (1.0.0rc1). Backend: libusb0

Notice also that more useful information is given, including details about the different backends (in this case ni and py).

Another utility is the VISA shell which was taken from the Lantz project. It provides a way to list, open and query devices. It also allows you to get (and in the near future set) attributes. The shell has in-built help, autocomplete and

$ python -m visa shell
Welcome to the VISA shell. Type help or ? to list commands.

(visa) list
(visa) open ASRL1::INSTR
ASRL1::INSTR has been opened.
You can talk to the device using "write", "read" or "query".
The default end of message is added to each message
(open) attr
|          VISA name          |  Constant  |        Python name         |                 val                 |
| VI_ATTR_ASRL_ALLOW_TRANSMIT | 1073676734 |       allow_transmit       |                  1                  |
|    VI_ATTR_ASRL_AVAIL_NUM   | 1073676460 |      bytes_in_buffer       |                  0                  |
|      VI_ATTR_ASRL_BAUD      | 1073676321 |         baud_rate          |                 9600                |
|    VI_ATTR_ASRL_BREAK_LEN   | 1073676733 |        break_length        |                 250                 |
|   VI_ATTR_ASRL_BREAK_STATE  | 1073676732 |        break_state         |                  0                  |
|    VI_ATTR_ASRL_CONNECTED   | 1073676731 |                            |          VI_ERROR_NSUP_ATTR         |
|    VI_ATTR_ASRL_CTS_STATE   | 1073676462 |                            |                  0                  |
|    VI_ATTR_ASRL_DATA_BITS   | 1073676322 |         data_bits          |                  8                  |
|    VI_ATTR_ASRL_DCD_STATE   | 1073676463 |                            |                  0                  |
|  VI_ATTR_ASRL_DISCARD_NULL  | 1073676464 |        discard_null        |                  0                  |
|    VI_ATTR_ASRL_DSR_STATE   | 1073676465 |                            |                  0                  |
|    VI_ATTR_ASRL_DTR_STATE   | 1073676466 |                            |                  1                  |
|     VI_ATTR_ASRL_END_IN     | 1073676467 |         end_input          |                  2                  |
|     VI_ATTR_ASRL_END_OUT    | 1073676468 |                            |                  0                  |
|   VI_ATTR_ASRL_FLOW_CNTRL   | 1073676325 |                            |                  0                  |
|     VI_ATTR_ASRL_PARITY     | 1073676323 |           parity           |                  0                  |
|  VI_ATTR_ASRL_REPLACE_CHAR  | 1073676478 |        replace_char        |                  0                  |
|    VI_ATTR_ASRL_RI_STATE    | 1073676479 |                            |                  0                  |
|    VI_ATTR_ASRL_RTS_STATE   | 1073676480 |                            |                  1                  |
|    VI_ATTR_ASRL_STOP_BITS   | 1073676324 |         stop_bits          |                  10                 |
|    VI_ATTR_ASRL_WIRE_MODE   | 1073676735 |                            |                 128                 |
|    VI_ATTR_ASRL_XOFF_CHAR   | 1073676482 |         xoff_char          |                  19                 |
|    VI_ATTR_ASRL_XON_CHAR    | 1073676481 |          xon_char          |                  17                 |
|     VI_ATTR_DMA_ALLOW_EN    | 1073676318 |         allow_dma          |                  0                  |
|    VI_ATTR_FILE_APPEND_EN   | 1073676690 |                            |                  0                  |
|    VI_ATTR_INTF_INST_NAME   | 3221160169 |                            | ASRL1  (/dev/cu.Bluetooth-PDA-Sync) |
|       VI_ATTR_INTF_NUM      | 1073676662 |      interface_number      |                  1                  |
|      VI_ATTR_INTF_TYPE      | 1073676657 |                            |                  4                  |
|       VI_ATTR_IO_PROT       | 1073676316 |        io_protocol         |                  1                  |
|   VI_ATTR_MAX_QUEUE_LENGTH  | 1073676293 |                            |                  50                 |
|   VI_ATTR_RD_BUF_OPER_MODE  | 1073676330 |                            |                  3                  |
|     VI_ATTR_RD_BUF_SIZE     | 1073676331 |                            |                 4096                |
|      VI_ATTR_RM_SESSION     | 1073676484 |                            |               3160976               |
|      VI_ATTR_RSRC_CLASS     | 3221159937 |       resource_class       |                INSTR                |
|  VI_ATTR_RSRC_IMPL_VERSION  | 1073676291 |   implementation_version   |               5243392               |
|   VI_ATTR_RSRC_LOCK_STATE   | 1073676292 |         lock_state         |                  0                  |
|     VI_ATTR_RSRC_MANF_ID    | 1073676661 |                            |                 4086                |
|    VI_ATTR_RSRC_MANF_NAME   | 3221160308 | resource_manufacturer_name |         National Instruments        |
|      VI_ATTR_RSRC_NAME      | 3221159938 |       resource_name        |             ASRL1::INSTR            |
|  VI_ATTR_RSRC_SPEC_VERSION  | 1073676656 |        spec_version        |               5243136               |
|     VI_ATTR_SEND_END_EN     | 1073676310 |          send_end          |                  1                  |
|   VI_ATTR_SUPPRESS_END_EN   | 1073676342 |                            |                  0                  |
|       VI_ATTR_TERMCHAR      | 1073676312 |                            |                  10                 |
|     VI_ATTR_TERMCHAR_EN     | 1073676344 |                            |                  0                  |
|      VI_ATTR_TMO_VALUE      | 1073676314 |                            |                 2000                |
|       VI_ATTR_TRIG_ID       | 1073676663 |                            |                  -1                 |
|   VI_ATTR_WR_BUF_OPER_MODE  | 1073676333 |                            |                  2                  |
|     VI_ATTR_WR_BUF_SIZE     | 1073676334 |                            |                 4096                |
(open) close
The resource has been closed.

Again, this release is only possible thanks to the contribution of a lot of people that contributed bug reports, testing and code. Thanks to everybody!

Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly.

Read the development docs: https://pyvisa.readthedocs.org/en/master/
or fork the code: https:/https://github.com/hgrecco/pyvisa/

Marcos Dione: testing-qt4-applicationswith-slots-and-signals


A few days ago someone said something[1] that reminded me about my audio player, which I had abandoned for more than a year already. The reason was mostly that the two Phonon backends, VLC and gstreamer, for some reason or other couldn't play the files I had without any gaps between songs.

To be honest, the first bug end up being me not properly encoding the filenames. If you first URL-encoded the filename and then built a Q/KURL with that, then it's all fine. It took me more than 12 months and a few rereads of the thread to realize it. Fixes apart, it seems that the bug still exists for other instances of gstreamer errors, so we're not out of the woods. In any case, I switched to the VLC backend and it seems that now is able to fire the aboutToFinnish() signal properly, so for the moment I'm using that.

All that is fine, but that's not what I wanted to talk about in this post. Given that this project largely precedes my interest on testing, it has no testing at all. Most of the project is straightforward enough to almost no need any, but there's a critic part that would not suffer at all if it had any, namely the Collections handling, including passing files from one to another and automatically updating new/removed Songs[2].

So after fixing the bug mentioned above I tried to figure out the current state of affaires regarding Collections, and boy, they're in bad shape. The code was locally modified, never commited, deactivating any notifications of filesystem changes (new or removed files), and other code I can't really understand the purpose of.

Because if this last detail is that I decided to start testing three classes: Collection, which handles a set a Songs with a common root directory; CollectionAggregator, which handles a set of collections and should coordinate moving a Song from one Collection to another; and CollectionIndexer, which scans from a Collection's root dir to find Songs.

All went fine while I tested the first class, Collection. There was a tricky part where I had to setup a QApplication in order to make signals work. The problems began when I started testing CollectionIndexer. Tests started blocking endlessly, signals stopped being either emited or firing the connected slots, life was bad.

I tried to search the available documentation and mailing lists for a hint about the problem, but besides a quite complex example that didn't seem to properly converge to anything useful, I was mostly on my own.

This morning I got my eureka moment: I noticed that if I executed each test class by itself, it worked, but both at the same time blocked and never finished. Then I remembered something said in QApplication's documentation:

For any GUI application using Qt, there is precisely one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time.

That was it: I was creating the application, first in the setUp() method, then as a class attribute, but I had one test class per class to test, each in its own file. Somehow this last fact lead me to think that somehow they were executed in separate processes, which is not true. Luckily, even with this limitation, there's none on the amount of times you can exec_() and quit() the same instance, so that's what I did: I created only one instance and reused it everywhere. I was already doing that for each test method, but again, somehow having several files mislead me to think they were isolated from each other.

So now all my unit tests work without mysteriously blocking forever. Now I just hope I can keep riding the success wave and bring satyr into good shape. A new release wouldn't hurt.

[1] No matter how much I try, I can't get any vaguer.

[2] Ok, maybe the Player/Playlist combo wouldn't hurt to have UTs either.

satyr pykde python

Hernán Grecco: Communicating with instruments using PyVISA but without NI-VISA


PyVISA is a Python frontend for the VISA library that enables controlling all kinds of measurement equipment through GPIB, RS232, USB and Ethernet among others interfaces.

Starting form version 1.6, PyVISA allows to use different backends. The cool thing is that your code remains the same, except the line in which you instantiate the resource manager (which tells which backend to use).

A few days ago I blogged about one of such alternative backends called PyVISA-sim which allows your to mock the presence of instruments (in cased that you missed the announcement, is here). Today I am making public a second backend.
Until now, talking to instruments via PyVISA required that you had National Instruments VISA library installed in your system. This works most of the time, for most people. But NI-VISA is a proprietary library that only works on certain systems. That is when PyVISA-py jumps in. It is an implementation of message based communication (Serial/USB/Ethernet) using Python and some well developed, easy to deploy and cross platform libraries (PySerial/PyUSB/Python Standard Library). In the near future it will also use linux-gpib to provide access to GPIB instruments in linux.

Cool, right? PyVISA without NI-VISA.

It actually started with an issue in the PyVISA tracker. A user wanted to use the LibreVISA library: an open source alternative to NI-VISA. While in principle this could work, it does not as LibreVISA is still incomplete. That is when it became obvious ... why not implementing parts of the VISA library in Python + friends? It would be open source, should be much easier to hack and compatible with PyVISA.

PyVISA-py is still young. Some very basic functionality is there but there still things to be done in order to implement all VISA features for message based sessions. But you can give it a try and provide feedback and why not code:

Just install (or upgrade) PyVISA 1.6 which is currently only available from GitHub:

$ pip install -U pyvisa

And then install:

$ pip install -U https://github.com/hgrecco/pyvisa-py/zipball/master

and then just instantiate your ResourceManager

import visa
rm = visa.ResourceManager('@py')

Notice that the rest of your code will be EXACTLY the same.

Remember that this is an early preview. We need your help to get it to the ready. Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly.

Or fork the code: https://github.com/hgrecco/pyvisa-py/

Hernán Grecco: Simulated devices in PyVISA: early preview


PyVISA started as wrapper for the NI-VISA library and therefore you need to install National Instruments VISA library in your system. This works most of the time, for most people. But sometimes you need to test PyVISA without the devices or even without VISA.

Starting form version 1.6, PyVISA allows to use different backends. These backends can be dynamically loaded. PyVISA-sim is one of such backends. It implements most of the methods for Message Based communication (Serial/USB/GPIB/Ethernet) in a simulated environment. The behavior of simulated devices can be controlled by a simple configuration in plain text. In the near future, you will be able to load this from file to change it depending on your needs.

To test it you need to install PyVISA 1.6 which is currently only available from GitHub:

$ pip install -U https://github.com/hgrecco/pyvisa/zipball/master

And then install:

$ pip install -U https://github.com/hgrecco/pyvisa-sim/zipball/master

For those of you interest in the internals, the plugin mechanism for PyVISA hooks at the VisaLibrary level. Mocking the Library allows for a comprehensive and powerful testing.

By the end of the week I will be blogging about another cool VISA backend which will be opened soon: PyVISA-py. It is a backend that does not require the NI-VISA library. Stay tuned!

Remember that this is an early preview. Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly.

Or fork the code: https://github.com/hgrecco/pyvisa-sim/

Hernán Grecco: PyVISA 1.6 brings comprehensive resources classes, thread-safety and more


PyVISA is a Python frontend for the VISA library that enables controlling all kinds of measurement equipment through GPIB, RS232, USB, Ethernet among others interfaces.

PyVISA 1.6 release is close and it brings several new nice things. One of the most visible improvements is the addition of a comprehensive set of resources classes, each mapping to a one of the 13 types of resources. Each class implements the methods and attributes that the specific session can handle, providing a Pythonic way to interact with the device (See here). This has allowed us to implement higher level functions such as the group execute trigger in the GPIB Interface.

PyVISA 1.6 brings a much better way to query a device for values, providing a comprehensive API to convert back and from ASCII and binary blocks. An API to write values to a device has been added (See here).

PyVISA 1.6 is thread-safe. While the VISA library has always been thread-safe, PyVISA was not. We have refactored the code removing several global variables that were used to handle state and tweaked the API accordingly.

PyVISA 1.6 continues on the road started with 1.5 to improve debugging, usability and reporting. The quality and density of logging messages have been improved as well as the information provided with the error messages. Python 3.4 Enums are now used to handle constants (the backported packaged enum34 is installed in older Python version).

There is one more change under the hood. PyVISA 1.6 can discover and use other backends to talk to devices (See here). This feature is allowing us to prototype some new packages about which I am going to blog next week.

All these things are only possible as we have dropped some backwards compatibility requirements. In particular, we have removed the legacy package, the string manipulation functions and all the singletons. Most programs will run without major changes but in any case, all API modifications are documented here to help with the transition.

All this would not have been possible without the support of a great community that has been helping with the development and testing different development versions. But we really need your help before uploading this to PyPI as an stable release. PyVISA is all about interacting with your operating system (finding and locating the C library) and you instruments. With the variety of platforms around, it is very difficult to test. We are asking all users to install PyVISA from the github repository and test it on your programs. You can install PyVISA or upgrade to the development version using pip:

$ pip install -U https://github.com/hgrecco/pyvisa/zipball/master

Again, this release is only possible thanks to the contribution of a lot of people that contributed bug reports, testing and code. Thanks to everybody!

Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly.

Read the development docs: https://pyvisa.readthedocs.org/en/master/
or fork the code: https:/https://github.com/hgrecco/pyvisa/

Facundo Batista: Satélites argentinos


Estos días fue lanzado exitosamente el tercer nanosatélite argentino, "Tita" (llamado así en honor a Tita Merello).

Se llaman "nanosatélites" porque, justamente, son mucho más chicos (y baratos) que los satélites "tradicionales". En particular, Tita pesa unos 25 kilos, está equipado con tres antenas y lleva una cámara para tomar fotos y videos en alta definición.

El satélite Tita, siendo instalado en el lanzador

Lo desarrolló la empresa argentina Satellogic, pero no lo lanzamos nosotros al espacio (todavía no tenemos esa capacidad), sino que fue lanzado desde la ciudad rusa de Yasny. Su objetivo es tomar imágenes durante tres años, en colaboración con otros nanosatélites, los ya lanzados Capitán Beto (llamado así obviamente en referencia a la canción de Spinetta) y Manolito (por el personaje de Mafalda), y a otros 15 satélites que Satellogic planea lanzar durante el próximo año.

Pero Tita es diferente a los dos anteriores, que pesaban alrededor de dos kilos. También es un prototipo, y usa las mismas estrategias de diseño y fabricación con componentes de uso comercial (resortes de ferretería, electrónica de teléfonos celulares y computadoras personales), pero este permite tomar imágenes y videos de dos metros de resolución. Esencialmente, la gente de Satellogic está haciendo lo mismo que hace un satélite convencional, pero a un precio entre cien y mil veces menor.

En este video bastante interesante podemos ver a Lino Barañao (Ministro de Ciencia y Tecnología) y Emiliano Kargieman (CEO de Satellogic), contándonos un poco todo esto (y de paso se ven pasos de la construcción, y las oficinas, ¡donde se ve bastante gente de PyAr trabajando!).

Como detalle final, les dejo este audio de Adrián Paenza hablando sobre los satélites (en general) en el programa La Mañana de Victor Hugo Morales.

Hernán Grecco: PyVISA 1.5 is out

   Publicado: PyVISA is a Python wrapper for the VISA library that enables controlling all kinds of measurement equipment through GPIB, RS232, USB and Ethernet. It has served the instrumentation community very well since 2005 (that's Python 2.3!) and still does.

However, Python and the different supported platforms have changed a lot in the recent years. We thought that PyVISA could use an update. Within the Lantz Project we did a small proof of principle of such update in visalib. Now we are taking what worked well and use it into PyVISA 1.5 (without changing the API!). In other words, PyVISA 1.5 brings several important changes in the underlying architecture without forcing you to change the programs.

Some time ago I posted that we were going beta. Now PyVISA 1.5 is finally released.

The new architecture is summarized here and the comparison with the previous one is here. Briefly you get Python 3 support, Mac OS X support, a better way to find libraries in your platform, an isolated ctypes wrapper. But the most important change is that the VISA library is not opened on import anymore. You can still use the instrument and get_instruments_list helpers (although we encourage not to do it!), but under the hood they will only instantiate a VisaLibrary object when you need them. We think that this will lead to more explicit and clear code, easier to deploy and to upgrade. There other small goodies around. Take a look at the docs.

You can install PyVISA or upgrade your previous version using pip:
$ pip install -U pyvisa

This release is only possible thanks to the contribution of a lot of people that contributed bug reports, testing and code. Thanks to everybody!

We are moving forward to make PyVISA even better. Submit your bug reports, comments and suggestions in the Issue Tracker. We will address them promptly.

Read the docs: http://pyvisa.readthedocs.org/
or fork the code: https:/https://github.com/hgrecco/pyvisa/

Martín Gaitán: Deploy de Django con Circus, Chaussette y Nginx


Aunque hay un pequeño mito al respecto, poner en producción una aplicación web hecha en Python no es tan complejo. Esa facilidad se debe a la estandarización de la pasarela WSGI, que define cómo se comunica (o se debería comunicar) una "app" (sea hecha con un framework o no) con un servidor web.

Si bien Nginx, el servidor web que está desplazando a Apache como el más popular tiene un módulo que implementa el estándar WSGI de manera nativa, la arquitectura más típica es utilizarlo como proxy reverso, conectado a un servidor WSGI especializado como Gunicorn que interactua con la aplicación web (posiblemente a través de multiples instancias o workers). Como queremos que nuestra app funcione permanentemente, el proceso WSGI y otros que sean necesarios (por ejemplo Redis) se demonizan de manera que sepan restaurarse automáticamente si mueren y sea posible monitorearlos: para eso suele usarse supervisor.


La arquitectura de deployment más común para una aplicación web Python

Si bien esta arquitectura está bastamente probada, hay una opción mejor.


El circo y el soquete

Circus y Chaussette son proyectos desarrollados por Tarek Ziadé y el equipo de Mozilla Sevices.


Tarek es un pythonista francés, core committer de Python y muchos proyectos relacionados. Recibió el reconocimiento de la PSF por sus aportes y es autor del gran libro Expert Python Programming

Una arquitectura de producción análoga a la descripta arriba, pero basada en Circus, se ve así:


Circus maneja procesos demonizados igual que Supervisor, pero además puede bindear sockets y manejarlos de la misma manera. Este desacople de la gestión de sockets del webserver WSGI permite muchas posibilidades, tanto en la gestión como en la escalabilidad de la arquitectura.

La capa WSGI en este esquema la aporta Chaussette, que tiene la particularidad que, en vez de abrir un socket nuevo, utiliza el que Circus abrió (y controla) para el worker. Además, aunque trae una implementación de WSGI built-in, puede usar muchos backends más eficientes o con características particulares como meinheld, gevent, gevent-socketio, entre muchos otros.

A diferencia de Supervisor que se basa en el protocolo XML-RPC para inspeccionar los procesos que controla, Circus utiliza un canal pub/sub basado en el mucho más moderno ZeroMQ (lo mismo que usa IPython Notebook) que permite un monitoreo realtime y una API de plugins mucho más simple. Otra diferencia, nada menor, es que Circus funciona con Python 2 o 3 (supervisor no es compatible con Python 3).

Y de yapa: Circus se puede usar como una biblioteca de muy alto nivel para la gestión no bloqueante de procesos. Se puede pensar con un wrapper de subprocess y/o multiprocess, que aporta información de monitoreo y estadísticas, control de flujo, una capa de señales (hooks) muy completa y más.

Desplegando Django

Para ejemplificar, voy utilizar un proyecto Django que estoy desarrollando (muy lentamente): nikolahub.

Circus se configura con un archivo con formato .ini. El mio, que bauticé circus.ini quedó así:

check_delay = 5
endpoint = tcp://
pubsub_endpoint = tcp://
stats_endpoint = tcp://

host =
port = 8080

cmd = /virtualenvs/nikolahub/bin/chaussette --fd $(circus.sockets.nikolahub) nikolahub.wsgi.application
use_sockets = True
numprocesses = 3

PYTHONPATH = /projects/nikolahub

La sección watcher indica lanza el comando a controlar, en este caso levantando 3 workers de la aplicación -django. Notar que como tengo instalado Chaussette dentro del virtualenv, uso el path absoluto al ejecutable. El fragmento --fd $(circus.sockets.nikolahub) se expande implícitamente asignando el pid que obtuvo el fork (el proceso hijo) de circus.

Si quisieramos usar otro servidor web, sólo hay que indicar cual con el parámetro --backend Por ejemplo:

cmd = /virtualenvs/nikolahub/bin/chaussette --backend gevent --fd $(circus.sockets.nikolahub) nikolahub.wsgi.application

Podemos probar si todo funciona:

(nikolahub)tin@morochita:$ circusd circus.ini
2014-06-12 04:36:16 circus[1141] [INFO] Starting master on pid 1141
2014-06-12 04:36:16 circus[1141] [INFO] sockets started
2014-06-12 04:36:16 circus[1141] [INFO] Arbiter now waiting for commands
2014-06-12 04:36:16 circus[1141] [INFO] nikolahub started
2014-06-12 04:36:16 circus[1141] [INFO] circusd-stats started
2014-06-12 04:36:17 circus[1150] [INFO] Starting the stats streamer
2014-06-12 04:36:17 [1149] [INFO] Application is <django.core.handlers.wsgi.WSGIHandler object at 0xa06f60c>
2014-06-12 04:36:17 [1149] [INFO] Serving on fd://5
2014-06-12 04:36:17 [1149] [INFO] Using <class chaussette.backend._wsgiref.ChaussetteServer at 0x9f2d6ec> as a backend
2014-06-12 04:36:17 [1148] [INFO] Application is <django.core.handlers.wsgi.WSGIHandler object at 0x939b60c>
2014-06-12 04:36:17 [1148] [INFO] Serving on fd://5
2014-06-12 04:36:17 [1148] [INFO] Using <class chaussette.backend._wsgiref.ChaussetteServer at 0x92596ec> as a backend

Tendremos la aplicación servida en el puerto 8080 de localhost. Demonizarlo es sólo un flag:

(nikolahub)tin@morochita:$ circud --daemon circus.ini

Para implementar nginx como proxy reverso armé un archivo nginx.conf:

server {
    listen 80;
    server_name nikolahub.nqnwebs.com;

    location /static/ {
            alias /projects/nikolahub/static/;

    location /media/ {
        alias /projects/nikolahub/media/;

    location / {
        proxy_pass http://localhost:8080/;
        proxy_pass_header Server;
        proxy_set_header Host $host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 600;
        proxy_send_timeout 600;
        proxy_read_timeout 600;

Luego agregamos el sitio:

$ ln -s /etc/nginx/sites-available/nikolahub nginx.conf
$ ln -s /etc/nginx/sites-enable/nikolahub nginx.conf
$ sudo service nginx restart

Esto pone a nginx como "frontend" de la aplicación, sirviendo los directorios con contenido estático y pasando el resto de las peticiones al puerto 8080 que administra Circus.

Ya tenemos nuestro sitio en producción.

El dueño del circo y los monitos

De ahora en más, podremos usar las herramientas que provee Circus.

circusctl es el dueño del circo. Puede parar, reiniciar, cambiar la cantidad de workers, abrir una consola ipython para interactuar o inspeccionar y mucho mas. Se puede usar como subcomandos (circusctl <subcmd> <watcher>) o usar la consola interactiva.

Por ejemplo, si quisiera ver cuantos procesos workers tengo y agregar uno más, podría hacer así:

(nikolahub)tin@morochita:$ circusctl numprocesses nikolahub
(nikolahub)tin@morochita:$ circusctl incr nikolahub
(nikolahub)tin@morochita:$ circusctl numprocesses nikolahub

Lo mismo y más se puede hacer desde una consola IPython.

(nikolahub)tin@morochita:$ circusctl ipython
Python 2.7.4 (default, Apr 19 2013, 18:32:33)
Type "copyright", "credits" or "license" for more information.

IPython 2.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: arbiter.numprocesses()
Out[1]: 4

circus-top es un monitor realtime, estilo top. Escucha las estadísticas que produce circusd-stats.

(nikolahub)tin@morochita:$ circus-top

circus-top en acción. Muestra los procesos watcher y los recursos que cosumen.

Todo esto puede verse y manejarse cómodamente a través de circus-web, un dashboard web que permite monitorear y administrar circus, con gráficos realtime y muy fácil de usar.


Desde las últimas versiones, circus-web se refactorizó para basarla en Tornado (originalmente usaba bottle) y hay que instalarlo aparte.

$ pip install circus-web


Circus es una herramienta que simplifica el stack de deployment de una aplicación web WSGI. La API de alto nivel, una arquitectura mucho más moderna y simple y el aval de ser desarrollada (y usada exhaustivamente) por Mozilla, son avales poderosos para probarla.

Como escribió el Marcos Luc "la función ya debería empezar (...) Bueno nena, buena suerte, cada vez la red te teme más..."

Damián Avila: Zen themes updated


OK, time to recap some things... As you know, Nikola 7.0.0 was released some weeks ago. It has a lot of improvements, bug fixes and new features. I recommend you to download and try it! As part of the release, we paid attention to update all the plugins and themes inside the Nikola Github organization (don't forget you can contribute with your own plugins and themes!). So, I updated my own themes, in particular, the Zen ones.

Read more… (2 min remaining to read)

Roberto Alsina: Nikola v7 finally out!


I am th­ri­lled to an­noun­ce ver­sion 7 of Niko­la, a sta­tic si­te and blog ge­ne­ra­tor is ou­t, wi­th a ba­zi­llion fea­tu­res and bu­gfixes (see be­lo­w).

You can get it at all the usual pla­ce­s, and he­re's the re­lea­se an­noun­ce­ment

He­re's the new fea­tu­res, the bu­gfixes list would make the post too long :-)

  • Added UNS­LU­GI­FY_­TI­TLES op­tion for making ti­tles fe­tched via the ­fi­le­na­me re­gexp pre­ttier (Is­sue #1282)
  • New de­pen­den­cie­s: na­tsort (na­tu­ral sor­ting in ga­lle­rie­s) and da­teu­til (re­pla­ces py­tz)
  • Niko­la.­co­m­man­ds are now the use­r-­friend­ly wra­ppers from con­so­le (Is­sue #1177)
  • Add a gi­thu­b_­de­ploy co­m­mand to de­ploy to Gi­tHub pa­ges (Is­sue #1208)
  • Re­mo­ve tidy fil­ter (it was bro­ken due to tidy being an­cien­t) (Is­sue #1164)
  • Added GE­NE­RA­TE_R­SS se­tting to allow di­sa­bling RSS in Niko­la (Is­sue #1236)
  • Li­nk lis­tings raw sour­ces if CO­P­Y_­SOUR­CES is True (Is­sue #1214)
  • Mu­ch mo­re po­wer­ful niko­la plu­gin co­m­mand (Is­sue #1189)
  • Mo­re po­wer­ful con­so­le mo­de allo­ws ac­ce­ss to all niko­la co­m­man­ds (Is­sue #830)
  • New `RO­BO­TS_EX­CLU­SION­S` op­tion lis­ting re­sour­ces to ex­clu­de from site­ma­p and in­clu­de in new ge­ne­ra­ted /ro­bo­ts.­txt (Is­sue #804)
  • Ge­ne­ra­te site­ma­pin­dex con­tai­ning RSS and site­map fi­les (Is­sue #804)
  • Su­pport hooks in tem­pla­tes, for use by plu­gins (Is­sue #896)
  • Use read­li­ne if avai­la­ble (Is­sue #1238)
  • Re­pla­ced REA­D_­MO­RE_­LI­NK wi­th IN­DEX_­REA­D_­MO­RE_­LI­NK an­d RSS_­REA­D_­MO­RE_­LI­NK (Is­sue #1222)
  • Added rea­din­g_­ti­me, re­mai­nin­g_­rea­din­g_­ti­me, pa­ra­gra­ph_­coun­t, ­re­mai­nin­g_­pa­ra­gra­ph_­count tags for REA­D_­MO­RE_­LI­NK (Is­sue #1220)
  • Add ca­no­ni­cal li­nk in lis­tings.
  • Added su­pport for new me­ta fi­les that are the sa­me for­mat as 1-­fi­le me­ta­da­ta, a­llo­wing for grea­ter fle­xi­bi­li­ty (Is­sue #954)
  • Co­lor­box is now in­ter­na­tio­na­li­zed (Is­sue #1205)
  • Added LO­GO­_URL and SHO­W_­BLO­G_­TI­TLE=­True se­ttings to fa­ci­li­ta­te sho­wing off lo­gos (Is­sue #1122)
  • Crea­te au­to­ma­tic sto­ry in­dex pa­ges for su­bfol­der­s, too (Is­sue #793)
  • New Slo­vak trans­la­tion by To­máš Prékop
  • Created a Ma­rk­do­w­nEx­ten­sion plu­gin cla­ss (Is­sue #1175)
  • The ba­se the­me pro­du­ces pro­per­ly sec­tio­ned and se­man­tic HT­M­L5 (Is­sues #1123, #1137)
  • The ba­se the­me co­mes wi­th a new sty­lish look by de­fault (Is­sue #1137)
  • The ba­se the­me su­ppor­ts Ri­gh­t-­to­-­Le­ft by using ::­di­r(r­tl) CSS4 ru­les an­d <ht­ml di­r="r­tl"> tags whe­re va­lid (Is­sue #1146)
  • Boots­trap 2 up­dated to 2.3.2 (via Is­sue #1137)
  • Added FOR­CE_I­SO­8601 se­tting that cu­rren­tly makes new_­post use ISO 8601 da­tes (via Is­sue #1156)
  • Added su­pport for TZ spe­ci­fied in post da­te (Is­sue #1118)
  • Make niko­la init ask about the si­te’s se­ttings (Is­sue #1080)
  • Use na­tu­ral sor­ting for fi­les and fol­ders list in lis­tings and ga­lle­ries (Is­sue #1144)
  • Added in­va­rian­ce tes­ting (Is­sue #672)
  • Plu­gins can in­ject tem­pla­tes in the sys­tem (Is­sue #1139)
  • niko­la im­por­t_wor­dpress now has a --­­q­­tran­s­­la­­te op­tio­n, to par­se pos­ts in the qtrans­la­te wor­dpress plu­gin for­mat and turn them in­to mul­ti­lin­gua­l ­Niko­la pos­ts (Is­sue #1072)
  • niko­la con­so­le allo­ws for in­ter­pre­ter choi­ce via -b, -i, -p; mo­reo­ve­r, ­su­pport for bp­y­thon is not de­pre­ca­ted an­y­mo­re (Is­sue #1126)
  • re­ti­red tag for pos­ts has been re­pla­ced wi­th pri­va­te (via Is­sue #686)
  • Chan­ged the de­fault TRANS­LA­TION­S_­PA­TTERN to "{­pa­th}.{­lan­g}.{ex­t}". (Is­sues #990, #829)
  • Ba­ckwar­ds com­pa­ti­bi­li­ty wi­th v5 is bro­ken. Added ba­ckwar­d­s-in­com­pa­ti­ble ­chan­ges. (Is­sue #829)
  • Added a CON­TEN­T_­FOOTE­R_­FOR­MA­TS con­fig op­tio­n. It is us­ed to for­ma­t ­the CON­TEN­T_­FOOTER va­ria­ble pro­per­l­y, for com­pa­ti­bi­li­ty wi­th ­the Trans­la­ta­ble Se­ttings fea­tu­re. The va­ria­ble takes a dic­t, the ke­ys of whi­ch are lan­gua­ges, and va­lues are (args, kwargs). (Is­sue #1112)
  • Cer­tain se­ttings are now trans­la­ta­ble. As of no­w, the se­ttings are: ­BLO­G_AU­THO­R, BLO­G_­TI­TLE, BLO­G_­DES­CRIP­TIO­N, LI­CEN­SE, CON­TEN­T_­FOOTE­R, ­SO­CIA­L_­BU­TTON­S_­CO­DE, SEAR­CH_­FOR­M, BOD­Y_EN­D, EX­TRA_HEA­D_­DA­TA, ­NA­VI­GA­TIO­N_­LI­NKS, REA­D_­MO­RE_­LI­NK (the up-­to­-­da­te list is avai­la­ble in ­SI­TE.­TRANS­LA­TA­BLE_SE­TTINGS) (Is­sues #851, #1057, #1061, #1112)
  • New Pos­t.au­tho­r() re­turns me­ta 'au­tho­r' or BLO­G_AU­THOR (Is­sue #1117)
  • Ship ba­se-­jin­ja, boots­tra­p-­jin­ja, boots­tra­p3-­jin­ja wi­th Niko­la (Is­sue #1104)
  • Re­mo­ve old me­ss­ages le­ft over for ba­ckwar­ds com­pa­ti­bi­li­ty: (Is­sues #829, #1105)
    • "Mo­­­re po­s­­ts abou­­t", re­­pla­­ced by "Mo­­­re po­s­­ts about %s"
    • "Po­s­­te­­d", re­­pla­­ced by "Po­s­­te­­d:"
    • "A­l­­so avai­­la­­ble in", re­­pla­­ced by "A­l­­so avai­­la­­ble in:"
  • Re­mo­ve old "s­l_­SI", "tr_­TR" lo­ca­le alia­ses (u­se "s­l" and "tr") (Is­sue #829, #1105)
  • New op­tion RSS_­PLAIN to op­tio­na­lly strip HT­ML from RSS fee­ds (Is­sue #1107)
  • Su­pport con­tent key in com­pi­ler­s' crea­te_­post (Is­sue #1098)
  • Use se­tup­tool­s’ ex­tras fea­tu­re. Use pip ins­ta­ll niko­la[ex­tra­s] to­ ins­ta­ll Niko­la wi­th ex­tras (re­­qui­­re­­men­­ts-ex­­tra­s.­­txt, for­mer­l­y re­­qui­­re­­men­­ts-­­fu­­ll.­­txt -- no­te the na­me chan­ge!) (Is­sue #1089)