Biblioteca grequests: peticiones asincronas en python

Una biblioteca muy utiliza hoy en día en python para hacer peticiones http es la fantástica requests (http://www.python-requests.org/en/latest/) de Kenneth reitz. Hoy os traigo del mismo autor un pequeño recubrimiento para utilizar esta biblioteca de manera asíncrona.

Grequests es un recubrimiento de requests utilizando gevent para hacer las peticiones asíncronamente.

Para instalarlo, como siempre:

pip install grequests

Lo mejor es un pequeño ejemplo para ilustrarlo:

import grequests

urls = [
    'http://www.deancos.com',
    'http://blog.deancos.com',
    'http://google.com',
]

rs = (grequests.get(u) for u in urls)

grequests.map(rs)

Como podemos ver es muy fácil de utilizar y utiliza los mismo métodos que su hermana mayor requests.

Para mas información, podéis visitar el github del proyecto: https://github.com/kennethreitz/grequests

5 años

Hoy hace cinco años de la publicación de este blog.

La verdad es que llevo en el mundo de los blogs desde hace muchos años, este no es el primero blog que he mantenido pero si quizás el mas longevo. La verdad es que escribo muy esporádicamente y sobre temas relacionados con el desarrollo pero muy dispares.

Este post es curiosamente el numero 55, el día que se cumplen 5 años, curiosamente también el 2015 :D vamos que estaba todo predestinado :P

Fuera de bromas, 55 post en 5 años son 11 post al año que son casi 1 al mes, no es mucho, pero visto con perspectiva esta bastante bien.

Desde hace tiempo no tengo constancia de las visitas al blog, cosa por otro lado que poco o nada me interesa, a decir verdad hace años veo este blog como algo para mi, una especie de diario con pequeñas recetas para mi mismo.

Una de las cosas que me animan de vez en cuando a escribir en el blog, es mi afición por la lectura y la escritura.

Me encantan los libros desde que tengo uso de razón, y me encanta escribir, cosa esta que la verdad no hago mucho últimamente por falta de tiempo.

Este blog me obliga de vez en cuando también a eso.

Volviendo al tema de la visitas, por si alguien tiene curiosidad la ultima vez que tuve constancia, tenia aproximadamente 200-300 visitas diarias, que no esta nada mal, teniendo en cuenta el poco contenido que genero y la poco visibilidad que tiene.

Esta entrada es bastante diferente a lo que suelo escribir. Simplemente lo escribo para agradecer a los lectores y personas que ha comentado alguna vez aquí, por pasarse por esta humilde morada y colaborar.

Muchas gracias, espero seguir 5 años mas escribiendo aquí.

Arduino Electronics Blueprints

Hoy quiero traer un pequeño libro en el que he colaborado como revisor, el libro escrito por Don Wilcher se titula Arduino Electronics Blueprints y como su titulo indica trata sobre Arduino.

La verdad es que ha sido divertido, he aprendido algunas cosas y creo que es un buen libro para iniciarse en la electrónica y/o programación con Arduinos. También me obliga a leer y escribir en ingles cosa que siempre viene bien. :D

Es la segunda vez que colaboro con PacktPub (www.packtpub.com) en la revisión de un libro, y supongo que en el futuro seguiré colaborando con ellos, y quien sabe si dar el salto y publicar mi propio libro, ¡Ideas no me faltan!

3601OS_Arduino Electronics Blueprints

Podéis encontrar mas información sobre el libro en: https://www.packtpub.com/hardware-and-creative/arduino-electronics-blueprints

Coffee Script

CoffeeScript (http://coffeescript.org/) es, tal como lo define su creador, un pequeño lenguaje que compila a Javascript.

Esta diseñado para ser intuitivo y fácil de leer, bebiendo de lenguajes como Ruby o Python.

La verdad es que para empezar a trabajar con CoffeeScript se debería tener conocimientos de javascript primero, y también ayuda y mucho conocer nodejs.

Vayamos al grano, vamos a instalar CoffeeScript (requiere nodejs):

npm install -g coffee-script

Este post no pretende ser ni siquiera una introducción al lenguaje, simplemente es un pequeño ejemplo de las capacidades del mismo. Si necesitas mas información podrás encontrarla en web oficial: http://coffeescript.org/#scripts

Muchas mas información mucho mas detallada podréis encontrar por ejemplo en el libro que escribió Javi Jimenez en español: https://leanpub.com/coffeescript o en ingles podréis encontrar valioso el coffeescript-cookbook: https://coffeescript-cookbook.github.io/

Por eso nosotros a lo nuestro que es mostrar un pequeño ejemplo sobre de que va esto:

class Upper
    constructor: (@text) ->
    all_words: ->
        @text.toUpperCase()
    first_words: ->
        (@text.split(' ').map (word) ->
            word[0].toUpperCase() + word[1..-1].toLowerCase()).join ' '
upper_instance = new Upper 'hola amigos'
console.log upper_instance.all_words ''
console.log upper_instance.first_words ''

Pero lo interesante de todo esto no es la funcionalidad del ejemplo, si no la compilación a javascript. Suponiendo que nuestro fichero se llama my_example.coffe podemos compilarlo a javascript:

$ coffee -c my_example.coffe

Obteniendo un fichero js con la misma funcionalidad:

// Generated by CoffeeScript 1.4.0
(function() {
  var Upper, upper_instance;
  Upper = (function() {
    function Upper(text) {
      this.text = text;
    }
    Upper.prototype.all_words = function() {
      return this.text.toUpperCase();
    };
    Upper.prototype.first_words = function() {
      return (this.text.split(' ').map(function(word) {
        return word[0].toUpperCase() + word.slice(1).toLowerCase();
      })).join(' ');
    };
    return Upper;
  })();
  upper_instance = new Upper('hola amigos');
  console.log(upper_instance.all_words(''));
  console.log(upper_instance.first_words(''));
}).call(this);

La verdad es que es un lenguaje divertido! 9 lineas coffee 20 javascript, aunque sinceramente el tema de si escribir mas o menos es mejor es subjetivo, creo que para algunas personas CoffeeScript puede ser un lenguaje que le ayude a escribir pequeños códigos en javascript sin despegarse mucho de su lenguaje preferido como podría ser Ruby o Python.

Redis y Python con redis-py

Hoy os presenta una pequeña receta para utilizar la biblioteca redis-py.

Básicamente instalamos la dependencia como siempre:

sudo pip install redis

Mini-ejemplo:

import redis

host = 'localhost'
conn = redis.StrictRedis(host=host)

# ejemplo de contador
conn.incr('bunch:key', 1)

# conseguir una key
conn.get('bunch:key')

# setear key
conn.set('other:a_key', 'test')

Básicamente con esto podrás utilizar el API de Redis para utilizarlo.

Puede encontrar mas información en: https://redis-py.readthedocs.org/en/latest/

Presentación Internet Of Things – BetaBeers + The Future Of The Net – Zaragoza Septiembre 2014

Presentación Internet Of Things – BetaBeers + The Future Of The Net – Zaragoza Septiembre 2014

Gracias los chicos de BetaBeers Zaragoza tuve el placer de poder estar alli y dar un pequeña charla sobre Internet de la cosas.

(los códigos de ejemplo podréis encontrarlo en: https://github.com/sdeancos/charla-betabeerszgz-ejemplos)

Web.py Skeleton (web.py + routing json + jinja2)

Hoy quería traerles un pequeño proyecto que he publicado en github, es un pequeño conjunto de ayudas pre-configuradas para comenzar un proyecto con el framework Web.py uno de mis preferidos para desarrollar rápidamente aplicaciones web.

Basicamente proporciona out-the-box:

  • Routing from json file.
  • Subapps system.
  • Jinja2 Support.
  • Flash message.

Las únicas dependencias del proyecto por ahora son el framework en si y el sistema de plantillas jinja2:

pip install web.py
pip install jinja2

Espero que sea útil para alguien, y si se puede mejorar los pull request son bienvenidos :D

Puedes descargarlo desde: https://github.com/sdeancos/webpyskeleton

Mandar stream de datos a Carriots con NodeJS

Os presento esta vez una receta sencilla para hacer una petición HTTP a la plataforma IoT Carriots.com y conseguir enviar una trama de datos esta vez con nodejs.

var https = require('https');

var send_stream = function(data){
    var device = 'YOUR_ID_DEVELOPER_DEVICE'
    var apikey = 'YOUR APIKEY'
    var stream = '{"protocol":"v2","device":"'+device+'","at":"now","data":{"key": "'+data+'"}}'

    var options = {
      host: 'api.carriots.com',
      path: '/streams',
      method: 'POST',
      headers: {'User-Agent': 'NodeJS-carriots.com-Client',
                'Content-Type' : 'application/vnd.carriots.api.v2+json;q=7',
                'Accept': 'application/vnd.carriots.api.v2+json;q=7',
                'Content-Length': stream.length,
                'Carriots.apikey': apikey}
    };

    var req = https.request(options, function(response) {
      console.log('STATUS: ' + response.statusCode);
      //console.log('HEADERS: ' + JSON.stringify(response.headers));
      response.setEncoding('utf8');
      response.on('data', function (chunk) {
        console.log('BODY: ' + chunk);
      });
    });

    req.on('error', function(e) {
      console.log('problem with request: ' + e.message);
    });


    req.write(stream);
    req.end();
};

send_stream('Value');

Espero que os sirva de referencia para poder hacerlo mas potente y crear prototipos con BeagleBone.

Mini-tutorial Silex: Autenticación (III)

En la anterior entrega (http://blog.deancos.com/2013/12/27/mini-tutorial-silex-anadiendo-dependencias-twig-ii/) vimos como podíamos integrar fácilmente el sistema de plantilla twig con Silex, gracias a lo cual ya podíamos maquetar nuestros resultados mas fácilmente.

Hoy vamos a dar un nuevo paso en nuestro pequeño programa y vamos a preparar nuestra aplicación para poder autenticar y autorizar.

Vamos a añadir una nueva dependencia al proyecto: Security.
Como vimos en los anteriores capítulos lo único que necesitamos es añadir la dependencia a nuestro composer.json:

   "symfony/security": "~2.3",

Una vez guardado el fichero tendremos algo como esto:

{
    "require": {
        "silex/silex": "~1.1",
        "twig/twig": ">=1.8,<2.0-dev",
        "symfony/twig-bridge": "~2.3",
        "symfony/security": "~2.3"
    }
}

Ahora podemos actualizar nuestro proyecto:

$ php composer.phar update

Bueno, ahora ya tenemos listas las dependencias que necesitamos para poder empezar a preparar nuestro entorno de seguridad.

Los primeros servicios que registramos son UrlGeneratorServiceProvider y SessionServiceProvider, ambos son servicios muy específicos que mas adelante utilizaremos, por ahora creo que sus nombre son bastante auto-explicativos.

Ya sabemos, en nuestro index.php registrar los servicios:

<?php
...
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\SessionServiceProvider());

Bueno, ahora vamos a registrar el servicio principal, SecurityServiceProvider, y lo configuraremos por defecto para poder hacer nuestras primeras pruebas. Por ahora como no tenemos aun base de datos podemos utilizar una configuración como la siguiente.

$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'admin' => array(
            'pattern' => '^/admin/',
            'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
            'logout' => array('logout_path' => '/admin/logout'),
            'users' => array(
                'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
            ),
        ),
    )
));

No entrare mucho a explicar como funciona la configuración pues en siguientes capítulos cuando lo integremos con la base de datos podremos explicarlo mas a fondo. Por ahora con saber que hemos configurado las rutas por defecto para poder hacer login/logout y que hemos creado un usuario admin es suficiente.

Ahora vamos a crear en nuestro controlador frontal una acción para hacer login:

$app->get('/login', function(Request $request) use ($app) {
    return $app['twig']->render('login.html', array(
        'error'         => $app['security.last_error']($request),
        'last_username' => $app['session']->get('_security.last_username'),
    ));
});

Y su vista correspondiente con el formulario de login:

<form action="{{ path('admin_login_check') }}" method="post">
    {{ error }}
    <input type="text" name="_username" value="{{ last_username }}" />
    <input type="password" name="_password" value="" />
    <input type="submit" />
</form>

En este punto os podréis preguntar que significa y de donde sale esta linea en la vista: path(‘admin_login_check’), pues efectivamente de uno de los servicios que antes registramos, exactamente de UrlGeneratorServiceProvider, que justamente se dedica a generar las urls que necesitamos de manera dinámica.

Bueno ya tenemos nuestra acción de login y su vista correspondiente.

Vamos a cambiar un poco lo que teníamos de capítulos anteriores para que tenga mas sentido con esta nueva funcionalidad, este seria nuestro nuevo controlador frontal:

<?php
require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\HttpFoundation\Request;

$app = new Silex\Application();
$app['debug'] = true;

$app->register(new Silex\Provider\TwigServiceProvider(), array('twig.path' => __DIR__.'/views',));
$app->register(new Silex\Provider\UrlGeneratorServiceProvider());
$app->register(new Silex\Provider\SessionServiceProvider());
$app->register(new Silex\Provider\SecurityServiceProvider(), array(
    'security.firewalls' => array(
        'admin' => array(
            'pattern' => '^/admin/',
            'form' => array('login_path' => '/login', 'check_path' => '/admin/login_check'),
            'logout' => array('logout_path' => '/admin/logout'),
            'users' => array(
                'admin' => array('ROLE_ADMIN', '5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsfods6LYQ8t+a8EW9oaircfMpmaLbPBh4FOBiiFyLfuZmTSUwzZg=='),
            ),
        ),
    )
));

$app->get('/', function () use ($app) {
    $user = $app['session']->get('user');
    return $app['twig']->render('index.html', array('user' => $user));
});

$app->get('/login', function(Request $request) use ($app) {
    return $app['twig']->render('login.html', array(
        'error'         => $app['security.last_error']($request),
        'last_username' => $app['session']->get('_security.last_username'),
    ));
});

$app->get('/admin', function () use ($app) {
    return 'Admin site';
});

$app->run();

Hemos añadido una nueva acción, /admin, para comprobar que funciona perfectamente el sistema de seguridad.


nota: la url /admin esta definida en la configuración de SecurityServiceProvider, es el valor de la clave pattern: 'pattern' => '^/admin/'

También hemos cambiado un poco nuestra vista, index.html:

Hello {{ user }}, welcome!
<p>
    <a href="login">Login</a>
    <a href="{{ path('admin_logout') }}">Logout</a>
</p>

Una de las lineas nuevas del controlador frontal que aun no hemos explicado en la utilización de la clase request para recoger la petición:

Para utilizarlo lo único que tenemos que hacer es importarla y utilizarla en nuestra acción:

use Symfony\Component\HttpFoundation\Request;
$app->get('/login', function(Request $request) use ($app) {}

Ahora si entramos con nuestro navegador preferido a nuestra aplicación podremos probar y experimentar con el sistema de seguridad.

En próximas entregas entraremos mas a fondo en estos temas y otros también muy interesantes.

Beaglebone configuración WiFi

Pequeña receta para configurar el acceso a internet mediante WiFi con la placa libre Beaglebone.

Yo solo he conseguido hacer funcionar con una tarjeta wifi Belkin Wireless G USB Network Adapter (F5D7050)

Lo que debemos hacer es enchufar nuestra tarjeta wifi a la placa y después crear el siguiente fichero en /var/lib/connman/wifi.config

$ vim /var/lib/connman/wifi.config

[service_home]
Type = wifi
Name = NombrePuntoAcceso
Security = wpa2-psk
Passphrase = PasswordPuntoAcceso

$ :wq!

Lo guardamos y reiniciamos la beagle. Si todo ha ido correctamente ya tendremos acceso a internet mediante WiFi en nuestra placa.

(Si alguien consigue hacerlo funcionar con otras tarjetas WiFi de otros fabricantes y/o otros chipsets podría comentarlo en los comentarios de este post)