Disponible Puppy Linux 5.3 'Slacko'

Ya está disponible versión 5.3 de Puppy Linux, una distribución ligera que ocupa menos de 125 MB, y que comparte compatibilidad binaria con Slackware (de hecho, comparte también el repositorio de paquetes). Esta distribución es idónea para equipos antiguos y/o con pocos recursos.

Las características más novedosas de esta versión son:
- Compatibilidad con Slackware 13.37
- Linux Kernel 2.6.37.6
- PMusic y Pequalizer para organizar y reproducir colecciones de música
- Frisbee Network Manager, para gestionar conexiones a redes inalámbricas
- Seamonkey como suite de navegador web y cliente de correo
- Gestión de paquetes de Slackware, Salix y Slacky, además de los paquetes PET de Puppy
- Ofimática con Abiword (procesador de textos) y GNumeric (hoja de cálculo)
- Soporte multimedia para muchos formatos





Referencias
Puppy Linux | Sitio oficial
Noticias Puppy | Noticias
Notas de la release | Liberación de Slacko
Recursos de Slacko | Blog de Barry Kauler

Aplicaciones Web sencillas con Python (y 2)

Plantillas
 
En el último ejemplo comenzamos a utilizar HTML, que, al fin y al cabo, es el medio por el cual presentaremos la información en el navegador. El problema que tenemos es que se mezcla el código de Python y de HTML, y
a la hora de depurar o realizar modificaciones, se vuelve enfarragoso y complejo. La forma ideal de trabajar sería separando la presentación (HTML) del código que procesa la información (Python). Por un lado estarían las etiquetas HTML que ponen la información, y por otro el código Python que accede a la base de datos y la prepara en estructuras de datos.
 
WebPy posee la característica de utilizar plantillas, que son directivas especiales embebidas en un código HTML, y que permiten conmutar valores que se pasan desde la capa de negocio o interactuar directamente con código Python.

Para estructurar nuestro código, vamos a crear un directorio donde se van a guardar las plantillas que vamos a necesitar. En nuestro caso la llamaremos plantillas. Dentro de este directorio crearemos un fichero llamado (por
ejemplo) plantilla.html, y cuyo contenido será el siguiente:

$def with (nombre, apellido)
<HTML>
   <HEAD></HEAD>
   <BODY>
   $if (nombre!='' and apellido!=''):
      <H1>Hola, $nombre $apellido</H1>
   $else:
      <b>ERROR:</b> No ha facilitado el nombre y el apellido
   </BODY>
</HTML>
 
La primera línea
 
$def with (nombre, apellido)
 
debe ser la primera de la plantilla, y se encarga de recoger los parámetros enviados desde el código de negocio, los cuales serán presentados en la página HTML.

A continuación se crea el código HTML. Cuando es necesario presentar la información, hemos creado una estructura de control if para comprobar los datos pasados. En nuestro caso comprobamos si nombre y apellido contienen datos, en cuyo caso imprimirá en un título el mensaje “Hola, “ seguido del nombre y del apellido. Si uno de los dos datos no se ha facilitado, entonces (else) se mostrará un mensaje de error.

Ha de notarse que anteponiendo el símbolo $ (dólar) a una línea en Python, esta se procesará como código Python. Asimismo, este símbolo también se utiliza dentro del HTML para sustituir una variable por su valor. Esta plantilla, por sí misma no hace nada, debe ser asociada a la capa de negocio. Para ello crearemos el código en un fichero situado fuera del directorio plantillas, justo en el nivel anterior. El código será el siguiente:


import web
 
urls = (
   '/hola', 'Saludo'
)
 
render = web.template.render('plantillas')
 
app = web.application(urls, globals())
 
class Saludo:
   def GET(self):
      data = web.input()
      nombre = data.nombre if 'nombre' in data else ''
      apellido = data.apellido if 'apellido' in data else ''
      return render.plantilla(nombre, apellido)
 
if __name__ == "__main__":
   app.run()
 
El objeto render apuntará al directorio donde se encuentran nuestras plantillas, creando internamente un objeto por cada plantilla encontrada.
 
En el método GET de la clase Saludo, hemos reforzado el código (a prueba de errores) en cuanto a los parámetros. Si se pasa el parámetro especificado, recogerá su valor. Si no se pasa, le asignará una cadena vacía. Los parámetros pasados están en formato diccionario, por lo que es posible averiguar si el parámetro (clave) está dentro del mismo (‘clave’ in diccionario).

Por último, se retorna lo generado por la plantilla. Para ello se invoca a la plantilla:

render.plantilla(nombre, apellido)
 
Como se comentó anteriormente, internamente, WebPy toma las plantillas dentro del directorio al que apuntaba, y generará un objeto accesible por cada una de ellas. A la plantilla le facilitará los parámetros nombre y apellido, que serán recogidos por la primera línea de éste ($def with).
 
Un ejemplo más complejo
 
Los ejemplos anteriores han sido muy básicos. Vamos a ver un poco más a fondo cómo podemos aprovechar todo lo anterior. Imaginemos que queremos hacer una consulta a un catálogo de productos. Esta consulta puede ser general (muestra todos los productos), o bien específica (muestra un producto determinado). La solución pasaría por implementar un acceso a base de datos. Pero para no extender demasiado este artículo, vamos a tenerlo completamente en memoria.
 
El código de negocio quedaría como sigue:

import web
 
urls = (
   '/ejemplo', 'Consulta'
)
 
render = web.template.render('plantillas')
 
app = web.application(urls, globals())
 
class Consulta:
   def GET(self):
      criterio = web.input()
 
      # Tuplas de diccionaris con datos de consulta.
      # Puede ser una carga de datos de una bbdd
      datos = (
         {'producto':'Tornillo', 'precio':0.45, 'marca':'Acme'},
         {'producto':'Tuerca', 'precio':0.55, 'marca':'Solme'},
         {'producto':'Clavo', 'precio':0.30, 'marca':'Calme'},
         {'producto':'Remache', 'precio':0.60, 'marca':'Acme'},
         {'producto':'Clavija', 'precio':0.95, 'marca':'Acme'},
         {'producto':'Grapa', 'precio':0.25, 'marca':'Tecme'}
      )
 
      registro=''
 
      if criterio:
         for i in range(0,len(datos)):
            if datos[i]['producto'] == criterio.producto:
               registro = datos[i]
               break
 
      if registro =='':
         registro = datos
 
      return render.productos(registro)
 
if __name__ == "__main__":
   app.run()
 
La llamada a la página puede hacerse sin parámetros (mostraría todos los productos), o bien pasando el parámetro producto, especificando cuál queremos consultar.

En ambos casos, a la hora de invocar a la plantilla, se pasaría la lista de productos o un único producto, que se almacena en la variable registro.
 

El código de la plantilla (productos.html) sería el siguiente:
 
$def with (registro)
<HTML>
   <HEAD></HEAD>
   <BODY>
   <TABLE BORDER='1'><TR BGCOLOR='#AAAAFF'>
   <TD><B>PRODUCTO<B></TD>
   <TD><B>PRECIO<B></TD>
   <TD><B>MARCA<B></TD></TR>
   $if 'producto' in registro:
      <TR>
      $for i in range(0,len(registro)):
         <TD> $registro.values()[i] </TD>
      </TR>
 
   $else:
      $for i in registro:
         <TR>
         <TD> $i['producto'] </TD>
         <TD> $i['precio'] </TD>
         <TD> $i['marca'] </TD>
         </TR>
 
   </TABLE>
   </BODY> 
</HTML>
 
En el caso de que se pase un único registro (la consulta se hizo por un único producto), éste será en sí un diccionario, por lo que al consultar si tiene una clave llamada producto, retornará el valor True. En tal caso, la función len() retorna el número de pares clave/valor del diccionario. Conociendo este valor, se recorre cada campo del diccionario en el bucle for y se extrae su valor, visualizándolo en una columna.

En el caso de pasar el catálogo completo, la función len() retornaría el número de filas (diccionarios) que contiene la lista. El acceso a la lista debe realizarse mediante un iterador (i), el cual recoge, uno a uno, cada fila (diccionario). El valor se extrae invocando el nombre de su clave. 
 
 
Conclusiones
Este breve tutorial cubre los aspectos más básicos, pero, a la vez, más potentes y flexibles, para comenzar a desarrollar aplicaciones Web mediante Python. A partir de las nociones vistas anteriormente, podremos empezar a
desarrollar complejas web dinámicas de una forma sencilla y eficaz.


 
Referencias
Lenguaje Python | Página oficial
Módulo mod_wsgi | Página oficial
WebPy | Página oficial
Apache | Página oficial

Aplicaciones Web sencillas con Python (1)

Este artículo está dedicado a aquellas personas que quieran dar sus primeros pasos en el desarrollo de aplicaciones web, y para aquellos que desarrollan aplicaciones sencillas, sin demasiadas complicaciones. Antes de redactar este artículo he estado probando y evaluando diversos frameworks para crear sitios web, tales como Bobo, Web2Py, CherryPy, Django, etc., pero al final me he decantado por WebPy, por su extrema sencillez para empezar, y por la similitud que tiene con otros frameworks de otros lenguajes, con lo que la curva de aprendizaje es óptima.

Más adelante, si los proyectos web se vuelven muy complejos y se requiere de elementos prefabricados y avanzados (como objetos persistentes a bases de datos, encriptación, modelo vista controlador, etc.), recomiendo utilizar los otros frameworks citados anteriormente (hay muchos más, pero éstos son más populares y potentes).

Se asume que el lector tiene conocimientos básicos de Python y que previamente tiene instalado el intérprete de Python en su máquina

Configuración del servidor Web
 
WebPy, a diferencia de otros frameworks, no posee un servidor de aplicaciones potente propio, y por ello, es mejor apoyarse en uno que ya esté funcionando. Entre los posibles candidatos se encuentran Apache, Lighttpd y nginx. Para este artículo he optado por Apache, dada su gran popularidad.

Una vez instalado Apache en nuestra máquina, es necesario agregar el módulo mod_wsgi, que permite hacer uso de Apache como servidor para aplicaciones escritas en Python. Este proyecto está alojado en http://code.google.com/p/modwsgi
 
Una vez descargado, si estamos usando Windows, renombrar el archivo a mod_wsgi.so y copiarlo al directorio modules de Apache. En el caso de Linux, compilar el módulo mod_wsgi (consultar: http://code.google.com/p/modwsgi/wiki/QuickInstallationGuide)
 
Una vez instalado el módulo, hay que configurar Apache para que reconozca dicho módulo. Para ello, editar el archivo httpd.conf (en el directorio conf de Apache), y agregar la siguiente línea en la misma parte en que Apache utiliza otras cargas LoadModule:
 
LoadModule wsgi_module modules/mod_wsgi.so
 
Al arrancar Apache desde la terminal debería dar un mensaje similar a éste:

Apache/2.2.2 (Unix) mod_wsgi/1.0 Python/2.3 configured
 
Si se lanzó desde Windows, el Apache Service Monitor, debería dar el mensaje en la parte inferior de la ventana.
 

Instalación de WebPy
 
Hay varias maneras de instalar WebPy (consultar http://webpy.org/download). Se puede descargar directamente la última versión desde la siguiente URL (consultar http://webpy.org/download para conocer cuál es la última versión):  http://webpy.org/static/web.py-0.34.tar.gz
 
También se puede descargar desde el repositorio en github: http://github.com/webpy/webpy

Una vez descargado, descomprimir el archivo tar.gz, y ejecutar la siguiente sentencia para instalarlo como librería en Python:
 
python setup.py install
 

Primera aplicación Web
 
Para ilustrar la sencillez de desarrollo de una página Web con WebPy, vamos a crear la típica aplicación “Hola, Mundo”.
 
import web
 
urls = (
   '/', 'index'
)
 
app = web.application(urls, globals())
 
class index:
   def GET(self):
      return "Hola, Mundo"

if __name__ == "__main__":
   app.run()
 
La variable urls es una tupla que contiene pares de direccionamientos URL y nombres de clase. En este ejemplo, el direccionamiento “/” (root), estará asociado a la clase index. Se pueden definir tantos pares como sean necesarios para la aplicación Web.
 
El objeto app contendrá la definición de la aplicación Web. En este ejemplo se asocian las URL’s de la aplicación a namespace global.
 
La clase index contiene un método GET, el cual se lanzará cuando se invoque a la página, pudiendo recibir parámetros. En su interior, retornará el literal “Hola, Mundo”, el cual se imprimirá en el navegador. Existe
también un método POST, que funciona como GET, pero ofuscando los parámetros. Estos dos métodos son los medios habituales de invocar a una página Web pasando (o no) parámetros.

Por último, las dos últimas líneas indican a WebPy que comience a servir páginas web con la configuración indicada.


Una vez se ejecuta este programa, el intérprete de Python se queda en modo de espera. El servicio Web está en marcha, esperando peticiones. Para probarlo, abrimos un navegador web e introducimos la URL: http://localhost:8080

Debería aparece nuestro bien conocido mensaje “Hola, Mundo”.


 
Parámetros y HTML
 
En una aplicación Web introduciremos elementos HTML para formatear el aspecto de las páginas. Además,  añadiremos dinamismo permitiendo que las páginas muestren datos parametrizados (por ejemplo, recogidos de un
formulario, o capturados de una base de datos).

Vamos a añadir más funcionalidad a nuestra aplicación anterior:

import web

urls = (
   '/hola', 'Saludo'
)
 
app = web.application(urls, globals())
 
class Saludo:
   def GET(self):
      data = web.input()
      return """
      <html>
      <head></head>
      <body background='#AAAAFF'>
      <h1>Hola, %s %s %s</h1>
      </body>
      </html>""" % (data.nombre, data.apellido1, data.apellido2)
 
if __name__ == "__main__":
   app.run()
 
El primer cambio lo hemos realizado en la sección de urls, donde ahora, el mapeo a la página Web será el siguiente:
http://localhost:8080/hola
 
Cuando se apunta a /hola, se invocará a la clase Saludo, concretamente a su método GET, en donde hemos agregado varios cambios. El primero de ellos ha sido definir una variable data, la cual recogerá los parámetros que se pasen por URL, lo que se consigue mediante la función input() del módulo web. Estos parámetros se recogerán en formato de diccionario, y son pares de parámetro y valor.

A la hora de retornar la salida, se retornará HTML, en donde hemos añadido un mensaje con formato de título (<h1>), un saludo con nombre y apellidos (extraídos de los parámetros pasados), los cuales se formatean mediante %s, e indicando después qué parámetros extraer.
 
Para invocar a la nueva página se pasan los parámetros en la misma URL, tal y como haría una llamada desde un formulario: http://localhost:8080/hola?nombre=Carmen&apellido1=Martinez&apellido2=Salguero

"Development Release" de Chakra lista para descarga



Desde hace muy poco tenemos a nuestra disposición la nueva versión de desarrollo de Chakra para descarga, como compilación de errores antes del lanzamiento estable.

En el anuncio oficial de Phil Miller podemos ver la notificación de varios cambios:

"El equipo de desarrollo de Chakra se enorgullece en anunciar la segunda versión "Edn", Chakra GNU/Linux con kernel 3.0.7 y KDE 4.7.2. Esta versión se caracteriza por un conjunto de herramientas actualizadas y una división de Qt y QtWebKit, lo que permite HTML 5 y soporte WebGL para los navegadores web Qt/KDE, GCC actualizado a 4.6.1, glibc a 2.14.1 ...", y mucho más.


Vía | DistroWatch | Descarga

Increíble baile sincronizado de ¿robots?... bueno, casi


2012, así se llama este último video musical de Genki Sudo y World Order, quienes ya habíamos visto en el proyecto realizado para la tablet Dell Streak.

Vía | Laughing Squid

Variaciones sobre Oneiric Ocelot [Wallpaper]


El pack de wallpapers "Variations on Oneiric Ocelot" está disponible para su descarga gracias al excelente trabajo de MadeInKobaia.

Descarga | deviantART

Cómo hacer malabares con 2 cubos de Rubik mientras resuelves otro sin morir en el intento [Video]


Cuando jugar con los cubos de Rubik ya no te parece tan divertido como antes, siempre puedes encontrar una solución al igual que David Calvo, el talento del video. ¿Te atreves a igualarlo?


Vía | Laughing Squid

¡Gracias a todos, commandcat celebra su primer año!



Desde commandcat queremos dar las gracias a todos nuestros lectores por su gran apoyo, por creer en lo que hacemos, por recomendarnos, ya que gracias a ustedes es por lo que seguimos adelante con esto de escribir y compartir entradas sobre Linux, tecnología y todas esas cosas que nos gustan del mundo 2.0. Ya cumplimos nuestro primer año en la blogósfera y nos alegra enormemente tener muchísimas visitas, enlaces amigos hacia a esta web, demasiados seguidores en las diferentes redes sociales, y a pesar de que en este momento quienes escribimos aquí estamos en unas pequeñas vacaciones (un poco ocupados con nuestros trabajos), esperamos volver con más fuerza y con nuestra habitual rutina de traerles información día a día.

De verdad que muchas gracias a todos, seguiremos adelante con este proyecto, esperando cumplir muchos años más. Esto continúa gracias a ustedes.

No olviden que cualquier recomendación, crítica o ayuda, nos pueden contactar a través de nuestro formulario o por nuestros perfiles en las diferentes redes sociales. ¡Gracias!

Asus Transfomer 2, La próxima transformación

Conoce gracias a este video sobre el nuevo ASUS Eee Pad Transformer 2, tablet que se fabricará con el nuevo procesador Nvidia Tegra 3 Kal-El y que estará disponible muy pronto, ofreciendo a los consumidores rendimiento y más duración en batería a comparación del primer ASUS Transformer, que a propósito, dura bastante.

Algunas de sus especificaciones son:
  • 1-1.3Ghz Quad (Quintuple) core Tegra 3 SoC
  • 1GB de RAM
  • Variantes de 16GB y 32GB en disco
  • Sistema operativo Android 4.0 Ice Cream Sandwich
  • Resolución 1280×800, Pantalla de 10.1 pulgadas





Vía | Android Authority

La Aurora Austral desde el espacio


Espectacular imagen y video de la Aurora Austral que fueron capturados desde el espacio por la NASA en septiembre 11 del año 2005.

"Desde el espacio, la aurora es una corona de luz que rodea cada uno de los polos de la Tierra. El satélite IMAGE capturó esta imagen de la aurora austral (luces del sur) el 11 de septiembre de 2005, cuatro días después del registro de una llamarada solar con plasma-un gas ionizado de protones y electrones- que voló hacia la Tierra."



Vía | Super Punch
Fuente | NASA Goddard Photo and Video

Python y SQLite

En el presente artículo vamos a aprender los conceptos básicos para desarrollar código en Python utilizando la base de datos SQLite. Se presupone que el lector conoce los conceptos básicos de Python y de SQL, y que ya tiene instalado en su máquina tanto el intérprete de Python como SQLite.

Librería pysqlite
 
Lo primero que debemos hacer es descargar e instalar la librería pysqlite desde su página web: 



http://code.google.com/p/pysqlite/
 
En el caso de tener Windows, descargamos un archivo ejecutable (.exe) y lo ejecutamos, instalándolo como cualquier aplicación Windows.
 
En el caso de tener Linux, descargamos el archivo comprimido (.tar.gz), y lo descomprimimos. Una vez  descomprimido, instalamos la librería mediante el siguiente comando:

$ python setup.py build
$ python setup.py install
 

Conexión a la base de datos
 
Para realizar una conexión a una base de datos SQLite, ésta debe estar arrancada:

$ sqlite3 mibasedatos.bbdd
 
Para realizar una conexión a una base de datos, importar la librería:

from pysqlite2 import dbapi2 as sqlite
 
A continuación se establece la conexión indicando el archivo de base de datos:
 
con = sqlite.connect('mibasedatos.bbdd')
 

Consultas de datos
 
Para todas las operaciones con la base de datos, hay que crear un cursor a partir de la conexión:
 
cur = con.cursor()
 
A partir del cursor, se pueden ejecutar las operaciones que se requieran, como la consulta de datos:

cur.execute('select campo from tabla')
 
Al ejecutar la consulta, el cursor apunta antes del primer registro o fila. Los siguientes comandos avanzan hasta el siguiente registro:
 
cur.next() # Avance
cur.fetchone() # Avance y recupera registro
 
Para obtener de una vez todos los registros del cursor:

cur = con.cursor()
cur.execute('select * from tabla')
result = cur.fetchall()
 
En la variable result se almacenará una lista o secuencia de tuplas, cada una de las cuales corresponde a un registro, y el valor de cada uno de los campos se encuentra separado por comas:

print result
[(0, u'valor1', 87), (1, u'valor2', 32), (2, u'valor3', 38)]
 
En este ejemplo, el resultado da 3 registros con tres columnas o campos, de los cuales, el primero y el último son numéricos, y el segundo es alfanumérico.
 
print result[1] # registro 2
(1, u'valor2', 32)
print result[2][1] # campo 2 del registro 3
valor3
 
Recorrer el resultado resulta muy sencillo, utilizando un iterador sobre la secuencia:
 
cursor = con.cursor()
cursor.execute('SELECT id, nombre, nick, password, rol FROM usuarios')
for fila in cursor:
   print 'id:', fila[0]
   print 'Nombre:', fila[1]
   print 'Nick:', fila[2]
   print 'Password:', fila[3]
   print 'Rol:', fila[4]
   print '*'*30
 

Actualizaciones
 
Por actualización se entiende toda aquella operación que realiza algún cambio, lo que implica algún tipo de escritura. Existen varios tipos de escritura o modificaciones en la base de datos. El primero afectaría únicamente a los datos de las tablas, lo que se consigue mediante las sentencias UPDATE, INSERT y DELETE de SQL. Otro afectaría a la estructura de la base de datos, pudiendo crear, modificar o eliminar tablas o índices.


Actualización de datos en tablas
 
Para todas ellas, se utilizará un cursor y la función execute(), tal y como vimos anteriormente:

from pysqlite2 import dbapi2 as sqlite
con = sqlite.connect("ticube.bbdd")
cur = con.cursor()
cur.execute("insert into tbconfig (parametro, valor,
descripcion) values ('PARAM1', '10', 'Parametro 1')")
cur.lastrowid
 
En este ejemplo se inserta un registro en una tabla. La última línea retorna el número de la última fila afectada en el cursor. Si sólo se realizó esta operación de escritura, pero no afecta a ningún registro, no retornará nada. Si todo fue bien, retornará (en este caso) 1.
 
El cursor acumulará operaciones de escritura, a medida que se vayan ejecutando. Pero estas operaciones no se hacen efectivas físicamente en la base de datos. Ello se debe a que se encuentran en una transacción.
 
Una transacción resulta muy útil cuando hay un encadenamiento de operaciones de escritura que tienen dependencias unas de otras. Cuando se completan todas las operaciones de escritura, si no se ha producido ningún
tipo de error, se puede procesar toda la transacción indicando a la conexión de la base de datos que perpetre definitivamente la transacción con todas las operaciones realizadas:
 
con.commit()
 
Si se produjera algún error durante la transacción, podrían abortarse todas las operaciones de escritura indicadas en el cursor para evitar inconsistencias de datos. Para ello, una vez se detecte algún error o inconsistencia, se indicaría a la conexión de la base de datos que dé marcha atrás, cancelando todas las operaciones realizadas:

con.rollback()
 

Actualización de la estructura de la BBDD
 
También es posible acceder y modificar la estructura de la base de datos, pudiendo crear nuevas tablas, añadir campos a las tablas existentes, crear o borrar índices, etc.

El proceder es idéntico a como hemos visto antes, a través del cursor. El siguiente ejemplo crea una sencilla tabla en nuestra base de datos:

cursor.execute("CREATE TABLE configuracion (parametro VARCHAR(30) NOT NULL, valor VARCHAR(30))")
 
A diferencia de la actualización de datos en las tablas, este tipo de actualizaciones se realiza directamente, y no requiere de transacciones.

 
Consultas parametrizadas
 
Imaginemos que se pretende hacer una carga masiva de datos de una tabla. En lugar de tantas sentencias INSERT como conjuntos de valores (cosa inviable si los datos son dinámicos), se pueden recoger éstos de otra consulta o de un fichero, y asignar dichos valores a unas variables y utilizar el valor de éstas en una única sentencia INSERT:

from pysqlite2 import dbapi2 as sqlite
 
con = sqlite.connect("ticube.bbdd")
cursor = con.cursor()
parametros=['UNO','DOS',’TRES’]
valores=['1','2','3']
max=len(parámetros)

for i in range(0,max):
   cursor.execute("INSERT INTO configuracion (parametro, valor) VALUES (?, ?)", (parametros[i], valores[i]))
con.commit()
 
En este ejemplo se insertarán 3 registros en la tabla configuración, obtenidos de dos secuencias (parametros y valores). El símbolo ? (interrogación), reserva el valor que va a tomar de la lista de parámetros que se especifican a continuación, en el mismo orden en que se enumeran.
 
Esta capacidad se puede aplicar también a otras consultas de actualización (como UPDATE o DELETE) o a consultas de datos (SELECT).

 
Cerrar siempre
 
SQLite es una base de datos muy versátil, ligera y práctica. Ello se consigue sacrificando una parte esencial en entornos distribuídos: la concurrencia. Así es: SQLite no es concurrente. Por ello, para evitar problemas e inconsistencias por la concurrencia, deberemos siempre cerrar todos los cursores y conexiones una vez han sido utilizados y no los utilicemos en cada módulo. Ello libera la conexión para nuevas operaciones. 

El método close() se encarga de esta operación:
 
cursor.close()
con.close()
 
El orden de apertura y cierre es importante:
1) Abrir conexión
2) Abrir cursor
3) Operaciones
4) …
5) Cerrar cursor
6) Cerrar conexión

Comparación del iPhone 4S con una Canon 5D Mark II


En este video realizado por Robino Films podemos apreciar una prueba de comparación de la capacidad de grabación de vídeo (1080p HD) que tiene el iPhone 4S contra una cámara Canon 5D Mark II.


Para este test se hicieron modificaciones en la configuración de exposición, velocidad de obturación, velocidad de cuadro, y estilo de imagen tanto como fue posible para una mejor comparación.


iPhone 4S

  • AE.AF bloqueado


Canon 5D Mark II


  • ISO 160 ~ 640 (variadas por inyección para que coincida con el iPhone)
  • F 7~22 ((variada por toma para que coincida con el iPhone))
  • Shutter 1/60th
  • Auto WB
  • Estilo de imagen estándar
  • 1080p 30

Vía | PetaPixel

El alfabeto de Star Wars


Conoce el alfabeto de Star Wars gracias al diseñador e ilustrador Fabian “Lishoffs” Gonzalez, el mismo autor del Simphabet.

Vía | El batiburrillo de Un Mundo Libre

Obviamente para Microsoft, el navegador más seguro, es Internet Explorer 9


Tal y como se observa en esta gráfica del nuevo sitio de Microsoft llamado Your browser matters, Internet Explorer 9 es el navegador más seguro del mercado, Chrome 14 y Firefox 7 apenas llegan a los talones de Internet Explorer 8, ganador del segundo puesto en esta calificación con criterios pocos confiables, a mi parecer.

Calificación navegador Chrome 14

Vía | Mundo Geek
© commandcat
Maira Gall