Como usar rtorrent des de cero

Viviendo en Alemania no puedo usar bitorrent sin que me llegue una factura por más de 500€ por bajar contenido que tiene copyright. Por lo que finalmente conseguí un servidor dónde tal cosa puede hacerse. El problema es que no tengo GUI por lo que tuve que buscar un cliente bittorrent para bajarme las cosas. Sin GUI, rtorrent era la primera opción que encontré. Al principio parece un poco complicado pero sabiendo los cuatro comandos básicos no ocasiona problemas.

Para iniciar el cliente de torrent:

$ rtorrent

Para poner un archivo en la cola de descargas tienes que presionar intro, pegar el enlace de magnet y darle a intro otra vez.
Una vez has hecho esto tienes el archivo en espera por lo que para iniciarlo usas las flechas arriba y abajo para localizar el archivo y con Control+S empiezas la descarga.
Si por algún motivo te dice que has movido el archivo (a mi me lo dice sin motivo) lo puedes solucionar con Control+E. Puedes cerrar el programa con Control+Q.
El fichero de configuración tiene que colocarse en ~/.rtorrent.rc y yo tengo el siguiente (por si lo quieres usar de base o del que me copié).

# This is an example resource file for rTorrent. Copy to
 # ~/.rtorrent.rc and enable/modify the options as needed. Remember to
 # uncomment the options you wish to enable.
 # Maximum and minimum number of peers to connect to per torrent.
 min_peers = 1
 max_peers = 20
 # Same as above but for seeding completed torrents (-1 = same as downloading)
 min_peers_seed = 1
 max_peers_seed = 20
 # Maximum number of uploads single torrent may use
 max_uploads = 10
 # Maximum number of simultaneous downloads
 max_downloads_global = 10
 # Maximum number of simultaneous uploads
 max_uploads_global = 20
 # Global upload and download rate in KiB. "0" for unlimited.
 download_rate = 0
 upload_rate = 300
 # Default directory to save the downloaded torrents.
 directory = /home/rocreguant/rTorrStuff/Downloads
 # Default session directory. Make sure you don't run multiple instance
 # of rtorrent using the same session directory. Perhaps using a
 # relative path?
 session = /home/rocreguant/rTorrStuff/session
 # Watch a directory for new torrents, and stop those that have been
 # deleted.
 schedule = watch_directory,5,5,load_start=./rtactive/*.torrent
 schedule = tied_directory,6,5,start_tied=
 schedule = untied_directory,7,5,stop_untied=
 # Close torrents when diskspace is low.
 schedule = low_diskspace,5,60,close_low_diskspace=2000M
 # Periodically save session data
 schedule = session_save,240,300,session_save=
 # Enable the default ratio group.
 ratio.enable=
 # Change the limits, the defaults should be sufficient.
 # Upload to a minimum ratio of 4.0
 ratio.min.set=400
 # Upload to a maximum ratio of 20.0
 ratio.max.set=2000
 # Upload a minimum of 250 MB
 ratio.upload.set=250M
 # When seeding ratio is reached close the torrent
 system.method.set = group.seeding.ratio.command, d.close=
 # Move files to ./unsorted when download completes
 system.method.set_key = event.download.finished,move_complete,"execute=mv,-n,$d.get_base_path=,./unsorted/;d.set_directory=./unsorted/"
 # Port range to use for listening.
 port_range = 60125-64125
 # Start opening ports at a random position within the port range.
 port_random = yes
 # Encryption options, set to none (default) or any combination of the following:
 # allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
 #
 # The example value allows incoming encrypted connections, starts unencrypted
 # outgoing connections but retries with encryption if they fail, preferring
 # plaintext to RC4 encryption after the encrypted handshake
 #
 encryption = allow_incoming,try_outgoing,enable_retry,prefer_plaintext
 # Sort the main view by ratio
 view.sort_current = main,greater=d.get_ratio=
 view.sort_new = main,less=d.get_ratio=
 view.sort = main
 # Sort the seeding view by the upload rate and only show torrents with peers
 view.sort_current = seeding,greater=d.get_up_rate=
 view.filter = seeding,"and=d.get_complete=,d.get_peers_connected="
 view.sort_new = seeding,less=d.get_up_rate=
 view.sort = seeding
 # Sort the leeching view by name
 view.sort_current = leeching,greater=d.get_name=
 view.sort_new = leeching,greater=d.get_name=
 view.sort = leeching
 # Filter the active view by connected peers
 view.sort_current = active,less=d.get_name=
 view.sort_new = leeching,less=d.get_name=
 view.filter = active,d.get_peers_connected=
 view.sort = active
 schedule = sort_main,11,5,view.sort=main
 schedule = sort_seeding,12,5,view.sort=seeding
 schedule = sort_leeching,13,5,view.sort=leeching
 schedule = sort_active,14,5,view.sort=active
 # Enable DHT support for trackerless torrents or when all trackers are down.
 # May be set to "disable" (completely disable DHT), "off" (do not start DHT),
 # "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
 # The default is "off". For DHT to work, a session directory must be defined.
 #
 #dht = auto
 # UDP port to use for DHT.
 #
 dht_port = 63425 
 # Enable peer exchange (for torrents not marked private)
 #
 #peer_exchange = yes

Que formato es el mejor para guardar números con decimales (float)?

Hace ya algunos días que le estoy dando vueltas al crear un script que me cogiera determinados datos y los fuera guardando en un archivo. Como quiero guardar muchos datos durante un largo periodo de tiempo he pensado que quizás debería empezar por lo básico. Que formato de archivo es mejor para almacenar este tipo de datos.

Para averiguar que formato es el ideal para tal propósito he ideado un script en python que lo que hace es generar cuatro números aleatorios entre -10 y 10 por cada una de las 100.000 hileras disponibles (en total 400.000 valores). Luego, usando el mismo data set, he almacenado esta información usando distintos formatos. Los formatos que he usado son texto plano, CSV, TSV, JSON, SQLite y HDF5. Estos formatos son los que me han parecido adecuados para este tipo de tarea. He dejado fuera XML porque me pareció que tiene gran similitud con JSON y realmente no necesito la jerarquía ni flexibilidad que este formato me ofrece.

Véase que el mismo script indica el tamaño de cada fichero. El tiempo de ejecución es de unos 65 segundos en mi laptop.

El script:


import numpy as np
import os
from os import listdir
from os.path import isfile, join

import json
import csv
import sqlite3
import h5py #pip install h5py

#generated 4 rows with number_of_floats data
def data_generation(number_of_floats):
	ret = np.ndarray((number_of_floats, 4))
	for i in range(number_of_floats):
		ret[i] = np.random.uniform( -10, 10, 4 )
	return ret

#standard text saving
def save_text_file(data):
	f = open('text.txt', 'w')
	for el in data:
		f.write(str(el).strip('[]'))
		f.write('\n')
	f.close()
	return True

#saving with json files
def save_json(data):
	f = open('json.json', 'w')
	j=json.dumps(data.tolist())
	json.dump(j, f)
	f.close()
	return True

#saving numbers on csv
def save_csv(data):
	with open('csv.csv', 'w') as csvfile:
		fieldnames = ['Col_A', 'Col_B', 'Col_C', 'Col_D']
		writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
		for el in data:
			writer.writerow({'Col_A': str(el[0]), 'Col_B': str(el[1]),'Col_C': str(el[2]),'Col_D': str(el[3])})
	return True

#Tab Separated Values (TSV)
def save_tsv(data):
	with open('tsv.tsv', 'w') as tsvfile:
		writer = csv.writer(tsvfile, delimiter='\t')
		for el in data:
				writer.writerow(el)
	return True

#save data in sqlite
def save_sqlite(data):
	conn = sqlite3.connect('data.sqlite3')
	cur = conn.cursor()
	cur.execute('DROP TABLE IF EXISTS Data ')
	cur.execute('CREATE TABLE Data (Col_A REAL, Col_B REAL, Col_C REAL, Col_D REAL)')
	for el in data:
		cur.execute('INSERT INTO Data VALUES ('+str(el[0])+', '+str(el[1])+', '+str(el[2])+', '+str(el[3])+')')
	conn.commit()
	conn.close()

#save the data in a hdf file
def save_hdf(data):
	h = h5py.File('data.hdf5', 'w')
	dset = h.create_dataset('data', data=data)

#check the file size
def show_file_size():
	mypath = '.'
	onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
	for fil in onlyfiles:
		statinfo = os.stat(fil)
		print 'name: '+str(fil)
		print 'size: '+str(statinfo.st_size)
		print ' '
	print onlyfiles

##############################
#
# Main
#
##############################

data = data_generation(100000)
save_text_file(data)
save_csv(data)
save_json(data)
save_csv(data)
save_tsv(data)
save_sqlite(data)
save_hdf(data)
show_file_size()
print 'Done'

Finalmente los resultados:

data-format-comparsion-plot

Formato Tamaño (Bytes)
Texto plano 4806060
CSV 5900742
TSV 7901330
JSON 8109034
SQLite 4468736
HDF5 3202144

Como se puede observar HDF5 es el ganador claramente siendo casi un 30% menor en tamaño que Sqlite que está ocupando el segundo lugar. No es de extrañar puesto que HDF es un formato de fichero diseñado especialmente para organizar y almacenar grandes cantidades de datos (ideado para supercomputadores). Para nuestra suerte las librerías tienen licencia BSD permitiendo mejoras y creación aplicaciones por parte de terceros. Lo que no me esperaba es que TSV obtuviera un tamaño similar a JSON y no a CSV. Sinceramente pensaba que CSV y TSV eran básicamente lo mismo.

Bonus: Para los interesados el script está en github.

Crea un negocio con alma budista, que tu declaración de intenciones sea Zen

Kickbox es una mini-guia, ofrecida por Adobe, bastante intuitiva sobre el método que usan para incorporar la innovación en sus oficinas. Para los interesados decir que es bastante simple pero bueno echarle un vistazo rápido.

El paso que me ha parecido más curioso es el del “Zen statement”. Su función es crear una declaración especifica, clara y concisa evitando todas las palabras con buzz (e.g. cutting-edge tech). Hecha bien la declaración puede ser una frase killer. La estructura de la frase es:

Mi idea es…

… un {producto/servicio descripción} para {target} que {valor principal} permitiendo {beneficios principales} a diferencia de {alternativas existentes}.

Ahora un ejemplo concreto para dejarlo más claro:

Mi idea es…

…un reproductor de musica potable para amantes de la musica que reproduce archivos musicales sin pérdidas de calidad permitiendo una definición extrema a diferencia de los iPods y otros reproductores de archivos comprimidos.

Esta es la idea del Zen statement. Vamos a desmenuzar un poquito los diferentes puntos.

  1. Define el producto o servicio: Que es tu producto en pocas palabras?
  2. Define tu consumidor target: Aunque creas que engloba a muchos trata de definir consumidores o empresas concretas. Mejor empezar con un target definido e ir ampliándolo.
  3. Define el valor clave: Piensa des del punto de vista del usuario, no tiene porque ser una funcionalidad o un beneficio.
  4. Define el beneficio más importante de tu producto: Que es lo que ofreces que es novedoso y útil?
  5. Nombra das alternativas más similares a tu idea: Que ofrecen tus competidores para suplir esta demanda?

Recuerda, aunque esto te pueda parecer una chorrada sirve para echarle el foco y tener claro el camino des del principio además de poder hacer un pitch en 5 segundos a cualquiera en cualquier situación.

Forzar GPy para que muestre el gráfico (plot)

Recientemente he estado programando con Gaussian processes framework in python (GPy) y no conseguía mostrar a través de un gráfico los resultados obtenidos. El problema es que al finalizar la ejecución del script la ventana con el gráfico también se cerraba automáticamente. Para solucionar esto se tiene que forzar la librería matplotlib que bloquee la ventana para así poder visualizar los datos. Si ubicamos la siguiente linea después del plot nos congelará la ventana evitando que se cierre al finalizar el la ejecución.

matplotlib.pylab.show(block=True)

Debugging con python

Para hacer debugging en python normalmente pongo prints pero a medida que el código crece los prints aumentan en número y al final me paso un buen rato buscando los sitios dónde los tengo. Por lo que al final he implementado una solución en la que puedes imprimir la linea y el mensaje deseado.

Lo que hace simplemente es usar el numero de linea que nos da la librería “inspect”. Aquí el código:

import inspect

def debug(message):
    print 'Debug in line', inspect.currentframe().f_back.f_lineno,':'
    print message

if __name__ == '__main__':
    debug('message')
    print '.'
    print '.'
    debug('message2')

Como complilar Latex en Ubuntu

Para compilar un documento de Latex solo necesitas un archivo que compilar (thanks Captain!) y un programa que te lo compile. Ejecutando el siguiente comando en nuestro Ubuntu instalaremos el paquete básico para tal propósito (~175MB):

sudo apt-get install texlive-latex-base

Aunque si lo quieres todo (paquetes de gráficos y muchas cosas raras) puedes usar el comando que te lo instala todo (~1.8GB):

sudo apt-get install texlive-full

Como leer anotaciones y comentarios de documentos PDF en Ubuntu

El visualizador de documentos de Adobe para cualquier distribución GNU/Linux, no vale nada. Básicamente lo que nos permite es simplemente “visualizar” el documento y no ofrece otras funcionalidades que aporta a otros sistemas operativos. Una de esta funcionalidad es la de visualizar anotaciones (simplemente se ve el subrayado).

Indagando un poco por la web he encontrado la solución. Lamentablemente no es una aplicación nativa para Ubuntu (las existentes al parecer solo muestran el documento), por lo que se tiene que hacer cosas un poco raras para ver las anotaciones. Así lo he solucionado yo:

Instalar Wine (aplicación nativa para Ubuntu que simula los procesos Windows para poder ejecutar programas que solo funcionan en Windows).

Si intentamos instalar Adobe PDF en Wine no nos va a funcionar (ninguna de las versiones). Por lo que tuve que encontrar otra aplicación. La aplicación que recomiendo es “PDF-XChange Viewer” tiene una versión pro (de pago) y una free. Para lo que necesitaba con la gratis me bastaba. Lo instalas y abres el documento abriendo primero el programa y luego yendo a buscar el archivo.

Espero que haya servido! :)

Arreglando el wifi después de actualizar a Lubuntu 14.04 LTS

Como ya comenté el otro día la actualización de Lubuntu 14.04 me rompió algunas configuraciones. A parte del teclado me rompió la recepción del señal de wifi. Me hizo desaparecer el gestor de la red (Network Manager).

Para hacerlo funcionar manualmente debemos usar el siguiente comando en la consola:

nm-applet

Pero para solucionarlo de forma permanente tendremos que ir al menú de Lubuntu luego preferencias y la opción de “Aplicationes por defecto para LXSession” (Default applications for LXSession). Una vez allí debereis escoger la pestaña Autostart y luego debajo de “aplicaciones manuales en autostart” (Manual autostarted applications) escribir “nm-applet” y darle al botón de “+ añadir” a su derecha. Para variar podéis reiniciar para ver que tiene efecto.

Arreglando el layout del teclado después de actualizar a Lubuntu 14.04 LTS

Si es que no aprendo. No es la primera vez que me pasa, las actualizaciones de Lubuntu siempre me crujen un par de configuraciones. Esta vez he tenido que arreglar el layout del teclado porque se me había cambiado al inglés y claro no hay Ñ ni acentos.

Para arreglar el teclado uno tiene que ir al menú principal, luego a preferencias y allí escoger “métodos de entrada de teclado” (keyboard input methods).

En la ventana que se nos abre seleccionaremos la pestaña “método de entrada” (input method). En la nueva pestaña seleccionaremos para “seleccionar un nuevo método de entrada” (select an input method ) y allí “mostraremos todos los métodos de entrada” (show all input methos).

En mi caso escogí el catalán y le daremos a añadir. Finalmente marcaremos el check box de “personalizar los métodos de entrada” (tick costumized input methods) y reiniciaremos para que los cambios tengan efecto.

Como ejecutar una tarea periódicamente en Ubuntu (Linux)

Esta programación periódica de tareas no sirve solamente para el uso en el ordenador personal, si no que también nos puede ser útil en el servidor. Estas tareas consisten en trabajos que el ordenador tiene que realizar cada determinado periodo de tiempo sin interferir con la UI.

Para conseguir tal objetivo todas las distribuciones Linux (incluyendo Ubuntu), y otros sistemas operativos basados en Unix, nos brindan la posibilidad de usar “Crontab”. El nombre proviene del antiguo dios griego Chronos encargado del tiempo.

Para ver las tareas que tenemos ejecutándose de forma periódica en nuestro sistema podremos usar el comando:

crontab -l

Si queremos modificar el fichero y añadir nuevos cronjobs deberemos usar el comando:

crontab -e

Este comando nos abrirá nuestro editor por defecto (en mi caso vi). Una vez dentro deberemos escribir una linea parecida a:

* * * * * /ruta/al/script.sh

 y si guardamos tal script será ejecutado regularmente en el margen de tiempo indicado. Cada asterisco representa una unidad de tiempo distinta. Ordenada en:

  • minutos ( de 00 a 59)
  • horas (de 0 a 23)
  • día del mes (de 1 a 31)
  • mes (de 1 a 12)
  • día de la semana( de 0 a 6) { Se empieza en domingo = 0 }

Los asteriscos tienen el significado de “todos”. Por lo que en este ejemplo significa que el script se ejecutará todos los minutos de todas las horas, de todos los días, de todos los meses, de todos los días de las semanas.

Para ejecutarlo el viernes a la 1 de la mañana:

0 1 * * 5 /ruta/al/script.sh

Si sólo queremos que se ejecute de lunes a viernes (el guión “-” nos permite indicar intervalos de tiempo):

0 1 * * 1-5 /ruta/al/script.sh

Para ejecutarlo cada diez minutos (las comas concatenan tiempos):

0,10,20,30,40,50 * * * * /ruta/al/script.sh

 pero también:

 */10 * * * * /ruta/al/script.sh

Dónde podemos apreciar porciones, evitándonos el uso de comas.

Los asteriscos, o indicaciones de tiempo, se pueden substituir por palabras protegidas.

@reboot Se ejecuta una vez al arranque
@yearly Se ejecuta una vez al año “0 0 1 1 *”
@annually (lo mismo que @yearly)
@monthly Se ejecuta una vez al mes “0 0 1 * *”
@weekly Se ejecuta una vez a la semana “0 0 * * 0″
@daily Se ejecuta una vez al dia “0 0 * * *”
@midnight (lo mismo que @daily)
@hourly Se ejecuta una vez cada hora “0 * * * *”

 

*/10 * * * * /ruta/al/script.sh >> /var/log/script_output.log 2>&1

 Empezando por el final, “2>&1” significa que tipo de información deseamos guardar. El “1” hace referencia al “standard output” y el “2” referencia a los “standard errors”. En el medio vemos “>>” que con solo una flecha significa que el fichero se sobre escribiría pero como lo que queremos es ir guardándolo todo, deberemos poner las dos flechas para que vaya añadiendo las nuevas lineas al final del documento. Tened en cuenta que si el cronjob lo ejecutas a menudo este fichero puede crecer con bastante velocidad causando problemas. Por lo que si queréis desechar lo que salga del script podéis usar

*/10 * * * * /bin/execute/this/script.sh > /dev/null 2>&1

Dónde “/dev/null” es un agujero negro que descarta toda la información que le llega.

Finalmente si queréis hacer limpieza podéis usar el siguiente comando:

crontab -r

Espero que os haya gustado y os haya servido! :)