diff --git a/AlejandroJCura/compactoexquisito/index.html b/AlejandroJCura/compactoexquisito/index.html
index 0372ae590..107150c4b 100644
--- a/AlejandroJCura/compactoexquisito/index.html
+++ b/AlejandroJCura/compactoexquisito/index.html
@@ -27,7 +27,7 @@
La ausencia de melodías en este disco parece algo planificado por Mansoor para volver a sorprendernos.
Y es que el vigesimosegundo disco editado en 2009 de este multifacético ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/AsociacionCivil/minutas/index.html b/AsociacionCivil/minutas/index.html
index 61b272e85..29d79e49b 100644
--- a/AsociacionCivil/minutas/index.html
+++ b/AsociacionCivil/minutas/index.html
@@ -31,7 +31,7 @@
2016-07-12 por IRC
2016-09-11 por IRC y Hangout">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/AsociacionCivil/mision/index.html b/AsociacionCivil/mision/index.html
index 86348f11c..b0ce95e0c 100644
--- a/AsociacionCivil/mision/index.html
+++ b/AsociacionCivil/mision/index.html
@@ -26,7 +26,7 @@
Sin fines de lucro la realización de todo tipo de actividades de fomento, promoción, protección, difusión y desarrollo del lenguaje de programación ">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/Bandera/descalificadas/index.html b/Bandera/descalificadas/index.html
index 3d0f9bde7..08303e4ce 100644
--- a/Bandera/descalificadas/index.html
+++ b/Bandera/descalificadas/index.html
@@ -34,7 +34,7 @@
Esta bandera debió ser descalificada porque no cumple con las reglas del concurso.
En particular, el ">
-
+
Ir al contenido principal
@@ -68,12 +68,12 @@
diff --git a/Bandera/variaciones/index.html b/Bandera/variaciones/index.html
index a4461077e..6ba14a639 100644
--- a/Bandera/variaciones/index.html
+++ b/Bandera/variaciones/index.html
@@ -31,7 +31,7 @@
Con PyAr en versalitas">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/CharlasAbiertas2010/introduccionalaprogramacion/index.html b/CharlasAbiertas2010/introduccionalaprogramacion/index.html
index 688a44928..c06b8034c 100644
--- a/CharlasAbiertas2010/introduccionalaprogramacion/index.html
+++ b/CharlasAbiertas2010/introduccionalaprogramacion/index.html
@@ -26,7 +26,7 @@
básicos de este arte de manera que dicha persona pueda, comprendiendo las bases de la disciplina,
tene">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/CharlasAbiertas2010/introduccionaldesarrollowebi/index.html b/CharlasAbiertas2010/introduccionaldesarrollowebi/index.html
index 21c3880a8..7e3285d16 100644
--- a/CharlasAbiertas2010/introduccionaldesarrollowebi/index.html
+++ b/CharlasAbiertas2010/introduccionaldesarrollowebi/index.html
@@ -26,7 +26,7 @@
principales del mundo web (HTML, HTTP, MVC, etc.), presentando la herramienta de desarrollo
!Web2Py, de mu">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/CharlasAbiertas2010/introduccionaldesarrollowebii/index.html b/CharlasAbiertas2010/introduccionaldesarrollowebii/index.html
index 8859b1a7b..0831df334 100644
--- a/CharlasAbiertas2010/introduccionaldesarrollowebii/index.html
+++ b/CharlasAbiertas2010/introduccionaldesarrollowebii/index.html
@@ -26,7 +26,7 @@
principales del mundo web (HTML, HTTP, MVC, etc.), presentando la herramienta de desarrollo Web2Py,
de muy">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/CharlasAbiertas2010/tallerjuegos/index.html b/CharlasAbiertas2010/tallerjuegos/index.html
index abc4788fa..3f7cac432 100644
--- a/CharlasAbiertas2010/tallerjuegos/index.html
+++ b/CharlasAbiertas2010/tallerjuegos/index.html
@@ -28,7 +28,7 @@
Día 9: Sábado 20 de Noviembre
10:30 a 15 ho">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/Conferencias/pyconar2014/index.html b/Conferencias/pyconar2014/index.html
index 3daaebb5a..2e7221d7d 100644
--- a/Conferencias/pyconar2014/index.html
+++ b/Conferencias/pyconar2014/index.html
@@ -26,7 +26,7 @@
PyConAr2014
(dejo este mensaje para quien llegue por link incorrecto)">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/GSoC/2022/index.html b/GSoC/2022/index.html
index 16e13e0b3..c89f7e38d 100644
--- a/GSoC/2022/index.html
+++ b/GSoC/2022/index.html
@@ -27,7 +27,7 @@
The following are the Python Argentina projects that could participate in Google Summer of Code 2022 (under the PSF org).
Ideas are tentative, please engage with the community">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/GSoC/2023/index.html b/GSoC/2023/index.html
index 33c5194d2..aa1184c29 100644
--- a/GSoC/2023/index.html
+++ b/GSoC/2023/index.html
@@ -27,7 +27,7 @@
The following are the Python Argentina projects that could participate in Google Summer of Code 2023 (under the PSF org).
Ideas are tentative, please engage with the community">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/GSoC/2024/index.html b/GSoC/2024/index.html
index f3cf7fa33..53e90f58d 100644
--- a/GSoC/2024/index.html
+++ b/GSoC/2024/index.html
@@ -27,7 +27,7 @@
The following are the Python Argentina projects that could participate in Google Summer of Code 2024 (under the PSF org).
Ideas are tentative, please engage with the community">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/HGTTP/contabilidad/index.html b/HGTTP/contabilidad/index.html
index b59b96e0f..47b5206b4 100644
--- a/HGTTP/contabilidad/index.html
+++ b/HGTTP/contabilidad/index.html
@@ -27,7 +27,7 @@
Previsibilidad Económica:
Para esta área es importante saber algunos datos: Elab">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/HGTTP/disertantes/index.html b/HGTTP/disertantes/index.html
index be02b1c01..48bbc3e2d 100644
--- a/HGTTP/disertantes/index.html
+++ b/HGTTP/disertantes/index.html
@@ -26,7 +26,7 @@
Keynotes: Invitados por la organización a hablar, esto es la cereza del postre de las charlas, la parte mas show del evento. Algunos tips a tener en cue">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/HGTTP/logistica/index.html b/HGTTP/logistica/index.html
index f22c84a60..8271f9f4c 100644
--- a/HGTTP/logistica/index.html
+++ b/HGTTP/logistica/index.html
@@ -29,7 +29,7 @@
Carteles en todos los lugares que vaya a haber o pasar gente con indicaciones de como llegar a los lugares asignados.
Carte">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/ListaDeCorreo/bar/index.html b/ListaDeCorreo/bar/index.html
index 132d977d6..ef502a231 100644
--- a/ListaDeCorreo/bar/index.html
+++ b/ListaDeCorreo/bar/index.html
@@ -26,7 +26,7 @@
no están relacionados con la promoción, difusión y temas técnicos del lenguaje de programación Python,
podés hacerlo suscribiéndote a: ht">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/ListaDeCorreo/migracion/index.html b/ListaDeCorreo/migracion/index.html
index eae4c9946..026fc14c9 100644
--- a/ListaDeCorreo/migracion/index.html
+++ b/ListaDeCorreo/migracion/index.html
@@ -27,7 +27,7 @@
1. empezar a probar desde todos los webmail">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/LlamadoasedePyconar2012/pyconar2012bsas/index.html b/LlamadoasedePyconar2012/pyconar2012bsas/index.html
index 82cdf972d..879956d51 100644
--- a/LlamadoasedePyconar2012/pyconar2012bsas/index.html
+++ b/LlamadoasedePyconar2012/pyconar2012bsas/index.html
@@ -27,7 +27,7 @@
Fecha: 12 al 17 de Noviembre de 2012 (--17 al 22 de Septiembre de 2012 o 1 al 6 de Octubre de 2012--)
Lugar: UNQUI (preconfirmada, ver: nota); UPE y UNGS (interesadas); UTN FRBA (">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/Noticias/2004/index.html b/Noticias/2004/index.html
index 2426dd1c6..958b37955 100644
--- a/Noticias/2004/index.html
+++ b/Noticias/2004/index.html
@@ -30,7 +30,7 @@
La última versión de Python ya está en la calle.
Ya está disponible el módulo decimal para Python 2.3.">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/Noticias/2007/index.html b/Noticias/2007/index.html
index df1cf55f8..bb7309273 100644
--- a/Noticias/2007/index.html
+++ b/Noticias/2007/index.html
@@ -26,7 +26,7 @@
Los días 6 y 7 de diciembre próximo se estará realizando la 3era edición del evento WhyFLOSS Conference en las instalaciones del Instituto Tecnológico de Buenos Aires (ITBA) de Puerto Made">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/Noticias/2008/index.html b/Noticias/2008/index.html
index 195cd40ca..e62cc59ed 100644
--- a/Noticias/2008/index.html
+++ b/Noticias/2008/index.html
@@ -26,7 +26,7 @@
Vamos a participar de Fábrica de Fallas, el 1er festival de Cultura Libre y Copyleft, que tendrá lugar el 15 y 16 de noviembre de 14 a 21 hs en FM La Tribu, Lambaré 873, Ciudad de Buenos A">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/Noticias/2009/index.html b/Noticias/2009/index.html
index 10fa7bd58..c6f29e542 100644
--- a/Noticias/2009/index.html
+++ b/Noticias/2009/index.html
@@ -26,7 +26,7 @@
VI Conferencia Latinoamericana de Software Libre | Latinoware 2009 Foz do Iguaçu – Paraná – Brasil
Del 22/10 al 24/10 se desarrolla este evento y Miembros de Python Argentina estarán presen">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/Noticias/pythonpalm/index.html b/Noticias/pythonpalm/index.html
index 3601f78bd..ade5c8699 100644
--- a/Noticias/pythonpalm/index.html
+++ b/Noticias/pythonpalm/index.html
@@ -28,7 +28,7 @@
==== Release Notes ====
Some months ago i did a p'>
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/Proyectos/CDPedia/Prensa/release08/index.html b/Proyectos/CDPedia/Prensa/release08/index.html
index 22b4c9e33..891f3b02a 100644
--- a/Proyectos/CDPedia/Prensa/release08/index.html
+++ b/Proyectos/CDPedia/Prensa/release08/index.html
@@ -28,7 +28,7 @@
Actualizamos el contenido a Diciembre 2012.
Renovamos completamente la gen">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/Proyectos/CDPedia/Prensa/release082/index.html b/Proyectos/CDPedia/Prensa/release082/index.html
index 17af41a2e..5914bc690 100644
--- a/Proyectos/CDPedia/Prensa/release082/index.html
+++ b/Proyectos/CDPedia/Prensa/release082/index.html
@@ -28,7 +28,7 @@
Actualizamos el contenido a Marzo 2014.
Uso más eficiente de los recurso">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/Proyectos/CDPedia/changelogs/index.html b/Proyectos/CDPedia/changelogs/index.html
index a94d71cec..0efe5a240 100644
--- a/Proyectos/CDPedia/changelogs/index.html
+++ b/Proyectos/CDPedia/changelogs/index.html
@@ -30,7 +30,7 @@
Set up fixed versions of CDPedia.
Merged enhance-home ">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/Proyectos/CDPedia/modoservidor/index.html b/Proyectos/CDPedia/modoservidor/index.html
index f12569a50..53f5cfde6 100644
--- a/Proyectos/CDPedia/modoservidor/index.html
+++ b/Proyectos/CDPedia/modoservidor/index.html
@@ -26,7 +26,7 @@
¿Cómo se arma esto?
Si corres ./cdpedia.py --help te mu">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Si corres ./cdpedia.py --help te muestra las opciones, pero básicamente hay 2 formas de montar un servidor. La más sencilla es utilizar el servidor web integrado con cdpedia y es la forma recomendada; la otra es usar un web server externo.
Usando el servidor integrado
Por ejemplo, para servir cdpedia en el puerto 80 en un hostname particular hacemos asi:
Obviamente el sudo es porque el 80 es un puerto privilegiado, sino directamente podemos poner lo siguiente para servir en una ip local y un puerto elevado.
-
./cdpedia.py--host=10.0.0.4--port=8080--daemon
+
./cdpedia.py--host=10.0.0.4--port=8080--daemon
Inclusive se puede configurar apache o el servidor que haya para que haga las veces de proxy reverso y asi servir todo en el 80.
Esta opción implica no usar el servidor web integrado y en cambio servir utilizando el modulo WSGI del servidor web que se quiera (mod_wsgi para apache, etc). Aún no encontramos razones convincentes de por qué se preferiría esta opcion por sobre el servidor integrado.
diff --git a/Proyectos/CDPedia/prensa/index.html b/Proyectos/CDPedia/prensa/index.html
index 7f06f27b0..f2e372cb3 100644
--- a/Proyectos/CDPedia/prensa/index.html
+++ b/Proyectos/CDPedia/prensa/index.html
@@ -35,7 +35,7 @@
Infobae: Reparten en escuelas argentinas DVD co">
-
+
Ir al contenido principal
@@ -69,12 +69,12 @@
diff --git a/Proyectos/RevistaPythonComunidad/PET1/desafio/index.html b/Proyectos/RevistaPythonComunidad/PET1/desafio/index.html
index e79b801e9..3069668fd 100644
--- a/Proyectos/RevistaPythonComunidad/PET1/desafio/index.html
+++ b/Proyectos/RevistaPythonComunidad/PET1/desafio/index.html
@@ -28,7 +28,7 @@
Ranking
De esta p">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/Proyectos/RevistaPythonComunidad/PET2/infopython/index.html b/Proyectos/RevistaPythonComunidad/PET2/infopython/index.html
index 3ccedbfd4..e23e9a4c8 100644
--- a/Proyectos/RevistaPythonComunidad/PET2/infopython/index.html
+++ b/Proyectos/RevistaPythonComunidad/PET2/infopython/index.html
@@ -45,7 +45,7 @@
Observaciones
Snippets son sintacticamente correctos. No se ejecutaron efectivamente por">
-
+
Ir al contenido principal
@@ -79,12 +79,12 @@
diff --git a/Proyectos/RevistaPythonComunidad/base/index.html b/Proyectos/RevistaPythonComunidad/base/index.html
index d78a01dc4..a0e67e752 100644
--- a/Proyectos/RevistaPythonComunidad/base/index.html
+++ b/Proyectos/RevistaPythonComunidad/base/index.html
@@ -27,7 +27,7 @@
Precisamos de un grupo u persona que arme la revista / editores :). Interesados, anotarse en el wiki. [OK]
Precisamos de un grupo u persona que este interesada en aportar articulos a la ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/Proyectos/RevistaPythonComunidad/pet2/index.html b/Proyectos/RevistaPythonComunidad/pet2/index.html
index 88fdfe41a..9f304f0b0 100644
--- a/Proyectos/RevistaPythonComunidad/pet2/index.html
+++ b/Proyectos/RevistaPythonComunidad/pet2/index.html
@@ -38,7 +38,7 @@
la autoría de las fotos corresponde a ellos
las fotos tienen licencias Creative Commons ">
-
+
Ir al contenido principal
@@ -72,12 +72,12 @@
diff --git a/Proyectos/alocadoalocador/index.html b/Proyectos/alocadoalocador/index.html
index ba5959da2..16e249c20 100644
--- a/Proyectos/alocadoalocador/index.html
+++ b/Proyectos/alocadoalocador/index.html
@@ -26,7 +26,7 @@
Un juego en 53 KB de puro código Python y pygame. Hecho para pydraw2006
https://opensvn.csie.org/PyAr/pydraw2006/release/">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/PyCamp/2009/TemasPropuestos/sprintdjango/index.html b/PyCamp/2009/TemasPropuestos/sprintdjango/index.html
index 31c35af5d..3341d190c 100644
--- a/PyCamp/2009/TemasPropuestos/sprintdjango/index.html
+++ b/PyCamp/2009/TemasPropuestos/sprintdjango/index.html
@@ -39,7 +39,7 @@
Un checkout del trunk de Dj">
-
+
Ir al contenido principal
@@ -73,12 +73,12 @@
diff --git a/PyCamp/2009/index.html b/PyCamp/2009/index.html
index 11830713c..b285378b8 100644
--- a/PyCamp/2009/index.html
+++ b/PyCamp/2009/index.html
@@ -38,7 +38,7 @@
Qué hace falta que alguien lleve
Qué conviene tener en ">
-
+
Ir al contenido principal
@@ -72,12 +72,12 @@
diff --git a/PyCamp/2009/naushikang/index.html b/PyCamp/2009/naushikang/index.html
index 5f378a58c..18e202b34 100644
--- a/PyCamp/2009/naushikang/index.html
+++ b/PyCamp/2009/naushikang/index.html
@@ -29,7 +29,7 @@
@foto_esta <url>: agrega la url tal como foto del qu">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/PyCamp/2009/quienesvan/index.html b/PyCamp/2009/quienesvan/index.html
index 9038140f8..6252e6099 100644
--- a/PyCamp/2009/quienesvan/index.html
+++ b/PyCamp/2009/quienesvan/index.html
@@ -30,7 +30,7 @@
FacundoBatista: desde el sábado a las 10, hasta el martes a las 19, morfo con todos, duermo ">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/PyCamp/2010/delinterior/index.html b/PyCamp/2010/delinterior/index.html
index 080def004..beec1521f 100644
--- a/PyCamp/2010/delinterior/index.html
+++ b/PyCamp/2010/delinterior/index.html
@@ -30,7 +30,7 @@
llego a retiro el 05/03 a las 7:00 hs aprox.
si al">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/PyCamp/2010/interesados/index.html b/PyCamp/2010/interesados/index.html
index ae22f9a2c..edcc30a51 100644
--- a/PyCamp/2010/interesados/index.html
+++ b/PyCamp/2010/interesados/index.html
@@ -26,7 +26,7 @@
Esta es la lista de interesados, para confirma">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/PyCamp/2010/pendientes/index.html b/PyCamp/2010/pendientes/index.html
index 35aa55ce4..d929aa20b 100644
--- a/PyCamp/2010/pendientes/index.html
+++ b/PyCamp/2010/pendientes/index.html
@@ -30,7 +30,7 @@
invitar a la gente: mandado el mail de invitación
c">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/PyCamp/2010/torneopingpong/index.html b/PyCamp/2010/torneopingpong/index.html
index d11c4b61f..3a413874c 100644
--- a/PyCamp/2010/torneopingpong/index.html
+++ b/PyCamp/2010/torneopingpong/index.html
@@ -34,7 +34,7 @@
Puede ser hoy (Sábado) por la noche, pero no sabemos si v">
-
+
Ir al contenido principal
@@ -68,12 +68,12 @@
diff --git a/PyCamp/2011/proyectoslaburados/index.html b/PyCamp/2011/proyectoslaburados/index.html
index cfcd97f61..fa0500715 100644
--- a/PyCamp/2011/proyectoslaburados/index.html
+++ b/PyCamp/2011/proyectoslaburados/index.html
@@ -28,7 +28,7 @@
geoarcade: Con el objetivo de introducir a nuevos en Dja">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/PyCamp/2012/TemasPropuestos/editordeebooks/index.html b/PyCamp/2012/TemasPropuestos/editordeebooks/index.html
index 1fced2864..aeaa8b6a8 100644
--- a/PyCamp/2012/TemasPropuestos/editordeebooks/index.html
+++ b/PyCamp/2012/TemasPropuestos/editordeebooks/index.html
@@ -26,7 +26,7 @@
Aunque no "apocalípticamente" como alguno preveían, la lectura de libros electrónicos se
hace cada más popular. Los lectores de libros electrónicos como el Kindle son cada vez más accesible'>
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/PyCamp/2012/index.html b/PyCamp/2012/index.html
index 653eb5e80..39c3547f4 100644
--- a/PyCamp/2012/index.html
+++ b/PyCamp/2012/index.html
@@ -42,7 +42,7 @@
de la Comunidad de Escuelas Argentino-">
-
+
Ir al contenido principal
@@ -76,12 +76,12 @@
diff --git a/PyCamp/2012/interesados/index.html b/PyCamp/2012/interesados/index.html
index 4e5f680ef..b8f53a01e 100644
--- a/PyCamp/2012/interesados/index.html
+++ b/PyCamp/2012/interesados/index.html
@@ -26,7 +26,7 @@
La inscripcion tiene dos etapas importantes:
Etapa 1: Para reservar la fecha n">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Proyectos En Los Que Se Trabajó Durante El Pycamp 2012
Usar el modo de edición de vim desde la línea de comandos (funciona en la consola de python):
-
set-ovi # bash
- bindkey -v # zsh
-
-Agregarlo al .bashrc o .zshrc respec. También se puede setear creando un .inputrc (en bash)
+
set-ovi # bash
+ bindkey -v # zsh
+
+Agregarlo al .bashrc o .zshrc respec. También se puede setear creando un .inputrc (en bash)
-
set editing-modevi
-setkeymapvi
-
-Hay muchas más opciones que se pueden setear (man 3 readline).
-
-Lista de comandos: `Bash vi editing mode cheat sheet`_
+
set editing-modevi
+setkeymapvi
+
+Hay muchas más opciones que se pueden setear (man 3 readline).
+
+Lista de comandos: `Bash vi editing mode cheat sheet`_
También vimos muchos plugins y cosas interesantes para agregarle a vim y que sea un mejor entorno de desarrollo con python. La mayoría está en https://github.com/fisadev/fisa-vim-config . Descubrimos que dos no andaban, uno ya está corregido (el que todavía no anda es el debugger, pero ya está identificado el problema). Y surgió la idea de meter el autocompletado de ninja ide en vim (como plugin). La gente de ninja va a separar la lógica del autocompletado como proyecto aparte, y nosotros vamos a meterlo en vim.
Spacecraft
diff --git a/PyCamp/2012/quellevar/index.html b/PyCamp/2012/quellevar/index.html
index e55fc4b77..6830fe460 100644
--- a/PyCamp/2012/quellevar/index.html
+++ b/PyCamp/2012/quellevar/index.html
@@ -36,7 +36,7 @@
Si tenes un rat">
-
+
Ir al contenido principal
@@ -70,12 +70,12 @@
diff --git a/PyCamp/2013/PosiblesSedes/votos/index.html b/PyCamp/2013/PosiblesSedes/votos/index.html
index 9f5dcefd6..f46240855 100644
--- a/PyCamp/2013/PosiblesSedes/votos/index.html
+++ b/PyCamp/2013/PosiblesSedes/votos/index.html
@@ -31,7 +31,7 @@
Estas fueron las votaciones en detalle:
Facundo Ba">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/PyCamp/2013/habitaciones/index.html b/PyCamp/2013/habitaciones/index.html
index 31285a7af..84f892282 100644
--- a/PyCamp/2013/habitaciones/index.html
+++ b/PyCamp/2013/habitaciones/index.html
@@ -29,7 +29,7 @@
No hay garantía 100% de que se respete esto a rajatabla, pero lo más probable es">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/PyCamp/2014/PosiblesSedes/votos/index.html b/PyCamp/2014/PosiblesSedes/votos/index.html
index fc3ffa040..17d436043 100644
--- a/PyCamp/2014/PosiblesSedes/votos/index.html
+++ b/PyCamp/2014/PosiblesSedes/votos/index.html
@@ -36,7 +36,7 @@
Diego Sarmentero
Hotel L">
-
+
Ir al contenido principal
@@ -70,12 +70,12 @@
diff --git a/PyCamp/2014/becas/index.html b/PyCamp/2014/becas/index.html
index 71d0a6331..fed5b65c7 100644
--- a/PyCamp/2014/becas/index.html
+++ b/PyCamp/2014/becas/index.html
@@ -26,7 +26,7 @@
Este año también habrán becas para facilitar el ir al PyCamp.
La idea es subvencionar lo más posible del costo total del PyCamp, en función de la cantidad de becas pe">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Crear tu keypair, usar los algoritmo RSA y SHA2, se sugiere usar un tamaño de 4096 bits
Imprimir varias etiquetas conteniendo información sobre tu keypair. Por ejemplo, múltlples copias por página de la salida del siguiente comando
-
gpg-v--fingerprint<IDdetukeypair>
+
gpg-v--fingerprint<IDdetukeypair>
o usando la utilidad gpg-key2ps del paquete signing-party (Debian/Ubuntu)
diff --git a/PyCamp/2015/PosiblesSedes/votos/index.html b/PyCamp/2015/PosiblesSedes/votos/index.html
index 5d679b20b..ed2602f2b 100644
--- a/PyCamp/2015/PosiblesSedes/votos/index.html
+++ b/PyCamp/2015/PosiblesSedes/votos/index.html
@@ -26,7 +26,7 @@
Para ver las posibles sedes podes verlo por acá
Si no po">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/PyCamp/2015/actividades/index.html b/PyCamp/2015/actividades/index.html
index 9db7c6cd0..126869eb5 100644
--- a/PyCamp/2015/actividades/index.html
+++ b/PyCamp/2015/actividades/index.html
@@ -29,7 +29,7 @@
Tenemos un pip-cache funcionando en el host alarm. ¡¡Por favor utilizarlo!!
Hay dos maneras de usarlo, la más simpl">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/PyCamp/2018/actividades/index.html b/PyCamp/2018/actividades/index.html
index ddfd2eea0..6c9306e82 100644
--- a/PyCamp/2018/actividades/index.html
+++ b/PyCamp/2018/actividades/index.html
@@ -27,7 +27,7 @@
Uso de Eventol en PyAr y mejoras para el sistema
Eventol es un proyecto libre que busca facilitar la administración y difusión ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/PyCamp/2018/index.html b/PyCamp/2018/index.html
index 23b23afaa..fadb78ced 100644
--- a/PyCamp/2018/index.html
+++ b/PyCamp/2018/index.html
@@ -27,7 +27,7 @@
Fechas:
28, 29, 30 de abril y 1 de mayo de 2018 (sábado, domingo, lunes y martes feriados (ambos) por el Día del Trab">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/PyCamp/2019/actividades/index.html b/PyCamp/2019/actividades/index.html
index 908c5d320..74df669d9 100644
--- a/PyCamp/2019/actividades/index.html
+++ b/PyCamp/2019/actividades/index.html
@@ -27,7 +27,7 @@
fades
Fixear algún bug o meter algún feature en fades (fades is a system that automatically handles the virtualenvs in the case">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Hoy hice Grillo, una herramienta que permite mandar datos de una máquina a otra re re fácil, usando micrófono
y parlantes para transmitir y leer la data por audio. Tiene magias como esta:
Y después de escuchar un ruido, máquina 1 tiene en su clipboard el contenido que tiene el clipboard de máquina 2.
Sirve para mandar textos y archivos también.
diff --git a/PyCamp/2019/index.html b/PyCamp/2019/index.html
index 7c73d68e5..40f1599ad 100644
--- a/PyCamp/2019/index.html
+++ b/PyCamp/2019/index.html
@@ -30,7 +30,7 @@
Qué ll">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/PyCamp/2020/index.html b/PyCamp/2020/index.html
index d6e160e87..91266cc29 100644
--- a/PyCamp/2020/index.html
+++ b/PyCamp/2020/index.html
@@ -27,7 +27,7 @@
Fechas:
21, 22, 23 y 24 de marzo (sábado, domingo, lunes (feriado puente) y martes feriado por el Día Nacional de la Memoria por la Verdad y la J">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/PyCamp/organizandounpycamp/index.html b/PyCamp/organizandounpycamp/index.html
index e3deb0581..395389919 100644
--- a/PyCamp/organizandounpycamp/index.html
+++ b/PyCamp/organizandounpycamp/index.html
@@ -28,7 +28,7 @@
El lugar debe contar con idealmente con espacio para albergar entre unas 35 y 50 personas aproximadamente (basado en la cantidad histórica de asistentes). Aunque exist">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/PyCamp/quesehace/index.html b/PyCamp/quesehace/index.html
index 13a13b588..94b3d67ed 100644
--- a/PyCamp/quesehace/index.html
+++ b/PyCamp/quesehace/index.html
@@ -28,7 +28,7 @@
Los interesados en proponer temas hacen un brevísimo speech para proponer una actividad, ">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/PyConArgentina/2012/distribucionafiches/index.html b/PyConArgentina/2012/distribucionafiches/index.html
index 8286d74d2..6ef701431 100644
--- a/PyConArgentina/2012/distribucionafiches/index.html
+++ b/PyConArgentina/2012/distribucionafiches/index.html
@@ -29,7 +29,7 @@
Como colaborar
Si estas cerca o tenes al">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/PyConArgentina/2012/encargadosaula/index.html b/PyConArgentina/2012/encargadosaula/index.html
index c49bdd988..23e09b380 100644
--- a/PyConArgentina/2012/encargadosaula/index.html
+++ b/PyConArgentina/2012/encargadosaula/index.html
@@ -26,7 +26,7 @@
Hay 16 bloques disponibles. Una misma persona puede solicitar varios bloques no-simultáneos.
Present">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/PyConArgentina/2013/llamadosedes/index.html b/PyConArgentina/2013/llamadosedes/index.html
index 84a57d0d1..013c2f2e9 100644
--- a/PyConArgentina/2013/llamadosedes/index.html
+++ b/PyConArgentina/2013/llamadosedes/index.html
@@ -28,7 +28,7 @@
Mejorar la forma de proponer sedes, con ">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/RemerasV2/cesarportela1/index.html b/RemerasV2/cesarportela1/index.html
index cc44dd673..01addba24 100644
--- a/RemerasV2/cesarportela1/index.html
+++ b/RemerasV2/cesarportela1/index.html
@@ -29,7 +29,7 @@
Comentarios
MarianoMara: ¿podrá ser con el logo de Python (PSF)">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/RemerasV2/cesarroldan2/index.html b/RemerasV2/cesarroldan2/index.html
index c057878e1..4bda645d3 100644
--- a/RemerasV2/cesarroldan2/index.html
+++ b/RemerasV2/cesarroldan2/index.html
@@ -31,7 +31,7 @@
[FacundoBatista] ¡Me gusta! ¿Por qué no en azul? algo que estaría bueno también es ponerle algo como... "Este cuerpo es Python powered", o a'>
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/RemerasV2/cesarroldan3/index.html b/RemerasV2/cesarroldan3/index.html
index 56ec33f4c..ecaac6285 100644
--- a/RemerasV2/cesarroldan3/index.html
+++ b/RemerasV2/cesarroldan3/index.html
@@ -32,7 +32,7 @@
[FacundoBatista] Me preocupa el tema de la impresión... ¿se ">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/RemerasV2/facundobatista5/index.html b/RemerasV2/facundobatista5/index.html
index 839f0a16d..2fd118a04 100644
--- a/RemerasV2/facundobatista5/index.html
+++ b/RemerasV2/facundobatista5/index.html
@@ -31,7 +31,7 @@
[LucioTorre, en la lista] Sin la URL atrás, pero sí adelante.
[FacundoBatista] Sigo esperando los colores, 😉">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/RemerasV2/juanjo1/index.html b/RemerasV2/juanjo1/index.html
index 1c89992fc..345377652 100644
--- a/RemerasV2/juanjo1/index.html
+++ b/RemerasV2/juanjo1/index.html
@@ -32,7 +32,7 @@
[FacundoBatista] No me gusta que no diga PyAr en ningún lado...
[JuanjoConti] Corregido!">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/RemerasV2/laubenech3/index.html b/RemerasV2/laubenech3/index.html
index 1aa5032f2..1e8286d3f 100644
--- a/RemerasV2/laubenech3/index.html
+++ b/RemerasV2/laubenech3/index.html
@@ -30,7 +30,7 @@
[RicardoKirkner] Hasta ahora una de las mejorcitas que vi. Ahora, haciendo referencia a lo que se charló en la lista, podría ser una variante en ">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/RemerasV2/laubenech4/index.html b/RemerasV2/laubenech4/index.html
index aa62bf571..1a6634e17 100644
--- a/RemerasV2/laubenech4/index.html
+++ b/RemerasV2/laubenech4/index.html
@@ -30,7 +30,7 @@
AlejandroJCura: Me encanta esta. Podría ser igual, pero con la boca un poco más cerrada? PD: guarda que el svg tiene dos colores delante y dos de">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/RemerasV2/nubis1/index.html b/RemerasV2/nubis1/index.html
index 2c4b6eb99..8a2a63d02 100644
--- a/RemerasV2/nubis1/index.html
+++ b/RemerasV2/nubis1/index.html
@@ -26,7 +26,7 @@
Unifico las dos propuestas ya que una vez hecho el shablon, es solo un cambio de colores (asi hay para todos los gustos)
Hay una version real con una modificacion posible s">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/RemerasV2/pabloziliani1/index.html b/RemerasV2/pabloziliani1/index.html
index c8a83eefa..8ff54b233 100644
--- a/RemerasV2/pabloziliani1/index.html
+++ b/RemerasV2/pabloziliani1/index.html
@@ -27,7 +27,7 @@
Una remera con solpiente
Dos versiones, una idea: mantener la identidad reusando la serpiente-sol que tenemos en la bandera. Uso solamente un color. Si alguna palabra no la entiend">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/RemerasV2/pabloziliani2/index.html b/RemerasV2/pabloziliani2/index.html
index 1a9689c18..58f8b2823 100644
--- a/RemerasV2/pabloziliani2/index.html
+++ b/RemerasV2/pabloziliani2/index.html
@@ -27,7 +27,7 @@
Una remera con explicación para personas grandes
http://www.franciscorobles.com.ar/libros/principito/pag01.htm Un solo color es suficiente. (nota: la tipografía usada en el svg es ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/TareasPendientes/tareasrealizadas/index.html b/TareasPendientes/tareasrealizadas/index.html
index 435bf3795..2ba17db81 100644
--- a/TareasPendientes/tareasrealizadas/index.html
+++ b/TareasPendientes/tareasrealizadas/index.html
@@ -32,7 +32,7 @@
Dar de alta ">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/aafigure/index.html b/aafigure/index.html
index 5bdda7f80..246422f3f 100644
--- a/aafigure/index.html
+++ b/aafigure/index.html
@@ -28,7 +28,7 @@
El nombre del parser es {{{aafig}}} y las opciones se agregan separadas por espacios.
Las opciones que requieren valores los toman luego d">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/adoptaunnewbie/index.html b/adoptaunnewbie/index.html
index bd88f969d..4d33ca906 100644
--- a/adoptaunnewbie/index.html
+++ b/adoptaunnewbie/index.html
@@ -26,7 +26,7 @@
que está buscando aprender de algo en particular, encuentre y se conecte con gente
que está dispuesta a mentorear en esos">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/alecutest2/index.html b/alecutest2/index.html
index c05b2bc71..e7867314a 100644
--- a/alecutest2/index.html
+++ b/alecutest2/index.html
@@ -26,7 +26,7 @@
Email: you AT SPAMFREE example DOT com You can even more obfuscate your email address by adding more uppercase letters followed by a leading and trailing blank.
...">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/alejandrodavidweil/index.html b/alejandrodavidweil/index.html
index f4fbd1151..0ed6451f0 100644
--- a/alejandrodavidweil/index.html
+++ b/alejandrodavidweil/index.html
@@ -26,7 +26,7 @@
Programo en Python desde, aproximadamente, el 2004.
La página Audio incluye varioas grabaciones de charlas acerca de python, es un link interesante.">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/alejandrojcura/index.html b/alejandrojcura/index.html
index f18ebd4a6..f08dc8169 100644
--- a/alejandrojcura/index.html
+++ b/alejandrojcura/index.html
@@ -29,7 +29,7 @@
ahora uso: buildbot, selenium, django.
Uso y me aburr">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/aprendiendopython/index.html b/aprendiendopython/index.html
index 9c0a3da9c..a5b383215 100644
--- a/aprendiendopython/index.html
+++ b/aprendiendopython/index.html
@@ -26,7 +26,7 @@
Antes que nada ¡FELICITACIONES!
Ahora ¿A dónde podrías recurrir para obtener información que te inicie en la programación pythonesca? Bueno, estos son algunos libros que se pr">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/asociacioncivil/index.html b/asociacioncivil/index.html
index e8e0eac98..4268908e7 100644
--- a/asociacioncivil/index.html
+++ b/asociacioncivil/index.html
@@ -26,7 +26,7 @@
Durante el 2014 se empezó a empujar en serio la idea de que Python Argentina sea una Asociación Civil.
Estamos discutiendo todo en esta lista de correo.">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/bandera/index.html b/bandera/index.html
index d7fb1c921..7cd85d1c1 100644
--- a/bandera/index.html
+++ b/bandera/index.html
@@ -28,7 +28,7 @@
Necesitamos una bandera con el logo de PyAr, para promocionarnos en charlas y conferencias.
Vamos a mandar imprimir una bandera gigante de Lona de ent">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/buzospyar/index.html b/buzospyar/index.html
index 30ab9bfb9..4ac7aa08d 100644
--- a/buzospyar/index.html
+++ b/buzospyar/index.html
@@ -26,7 +26,7 @@
Vamos a hacer buzos de Python Argentina!. ¿ Las razones ?, juntar dinero para PyAr, y que podamos tener un espectacular buzo de Python Argentina!!.
Los buzos son de tela de ">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/callforcharlastemplate/index.html b/callforcharlastemplate/index.html
index 839b15638..ba1d3ac20 100644
--- a/callforcharlastemplate/index.html
+++ b/callforcharlastemplate/index.html
@@ -26,7 +26,7 @@
PyCon Argentina ANIO – URL CONFNUM Conferencia Argentina de Python FECHA LUGAR
PyAr, el Grupo de Usuarios de Python de Argentina invita a toda la comunidad de usuarios de Pytho">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Cdpedia-on-android es una aplicación android que permite correr la Cdpedia en este sistema operativo.
Para que funcione correctamente es necesario tener descomprimido (no soporta el archivo .iso) alguno de los releases de la cdpedia en la carpeta /mnt/sdcard/cdpedia. A continuación una mini receta:
Si querés probar la primera versión de la aplicación para android, podés descargarte el .apk desde
acá.
diff --git a/cfcpyconar2011/index.html b/cfcpyconar2011/index.html
index 9d9a9af8a..6f528bb70 100644
--- a/cfcpyconar2011/index.html
+++ b/cfcpyconar2011/index.html
@@ -31,7 +31,7 @@
Universidad Nacional del Noroeste de la Provincia de Buenos Aires
PyAr, el Grupo de Usuarios ">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/charlas/index.html b/charlas/index.html
index af1f1fa6f..0879cb6ac 100644
--- a/charlas/index.html
+++ b/charlas/index.html
@@ -35,7 +35,7 @@
Un juego en 7 días
Introducción a Py">
-
+
Ir al contenido principal
@@ -69,12 +69,12 @@
diff --git a/chistes/index.html b/chistes/index.html
index 39b3524a1..9a62fc856 100644
--- a/chistes/index.html
+++ b/chistes/index.html
@@ -32,7 +32,7 @@
> Por la poca experiencia que tengo en tg,">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/colectadehardware/index.html b/colectadehardware/index.html
index 05352e44d..dde831add 100644
--- a/colectadehardware/index.html
+++ b/colectadehardware/index.html
@@ -28,7 +28,7 @@
Show me the SILICONNN!!!
Cortita y al pie, en usla nos ofrecieron housing y la verdad que nos hace falta una maquina para meter todos nuestro">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/compilarpython/index.html b/compilarpython/index.html
index 5a86ed6e4..e41c3ec94 100644
--- a/compilarpython/index.html
+++ b/compilarpython/index.html
@@ -27,7 +27,7 @@
Compilando Py3k
Para compilar primero tenemos que descargar las fuentes desde el repositorio. Para eso, debemos tener un clie">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Para compilar primero tenemos que descargar las fuentes desde el repositorio. Para eso, debemos tener un cliente de subversion ("sudo aptitude install subversion" en linux basados en debian)
el comando que hay que correr es el siguiente
-
svn co http://svn.python.org/projects/python/branches/py3k/
+
svn co http://svn.python.org/projects/python/branches/py3k/
luego debemos tener instalados los archivos de desarrollo para poder tener habilitados algunos módulos de Python; si no los instalamos, esos módulos no van a estar disponibles.
La lista con los nombres en linux basados en debian es:
@@ -106,47 +106,47 @@
Compilarpython
libdb-dev
Luego de instalar todas las librerías debemos correr los siguientes comandos:
-
cd py3k
-./configure
-make
-sudo make install
+
cd py3k
+./configure
+make
+sudo make install
Si todo salió bien, ahora podemos usar python 3.
Podemos probar corriendo el comando python3.0 en la consola:
-
mariano@mousehouse:~/Software/py3k$ python3.0
-Python 3.0rc1+ (py3k:66685, Sep 29 2008, 17:25:48)
-[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
-Type "help", "copyright", "credits" or "license" for more information.
->>>
+
mariano@mousehouse:~/Software/py3k$ python3.0
+Python 3.0rc1+ (py3k:66685, Sep 29 2008, 17:25:48)
+[GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2
+Type "help", "copyright", "credits" or "license" for more information.
+>>>
Cada vez que queramos actualizar al código más nuevo en el repositorio, debemos hacer lo siguiente:
-
cd py3k
-svn up
-make
-sudo make install
+
cd py3k
+svn up
+make
+sudo make install
Cómo armar un paquete DEB de Python
A veces es necesario armar un paquete para facilitar la instalación/desinstalación y pruebas en distintas máquinas.
Aquí un ejemplo de cómo hacerlo para Debian o Ubuntu (bajando py3k):
Bajamos y descomprimimos (en este caso, por SVN):
-
svn co http://svn.python.org/projects/python/branches/py3k py3k
-cd py3k
+
svn co http://svn.python.org/projects/python/branches/py3k py3k
+cd py3k
diff --git a/contribuyendoalwiki/index.html b/contribuyendoalwiki/index.html
index fd0cfc26a..965943cdb 100644
--- a/contribuyendoalwiki/index.html
+++ b/contribuyendoalwiki/index.html
@@ -26,7 +26,7 @@
falta que sea un usuario registrado de la web.
Hay algunas páginas especiales que sólo pueden ">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/danielmendoza/index.html b/danielmendoza/index.html
index 4078f803b..4b154e3fa 100644
--- a/danielmendoza/index.html
+++ b/danielmendoza/index.html
@@ -28,7 +28,7 @@
Hola a todas, describire brevemente mi persona, o algunas actividades que realizo.
Soy Analista Universitario en Sistemas de Infor">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/dbapi/index.html b/dbapi/index.html
index 4f8e54ab8..8c94414ef 100644
--- a/dbapi/index.html
+++ b/dbapi/index.html
@@ -31,7 +31,7 @@
En python, el acceso a bases de datos esta estandarizado por la especificac">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
Una vez establecida la conexion, hay que crear un "cursor". Un cursor es una estructura de control que se usa para recorrer (y eventualmente procesar) los records de un result set.
El metodo para crear el cursor se llama, originalmente, cursor():
-
>>>cursor=db.cursor()
+
>>>cursor=db.cursor()
Ya tenemos la conexion establecida y el cursor creado, es hora de ejecutar algunos comandos SQL:
-
>>>cursor.execute("SELECT * FROM Students")
-5L
+
>>>cursor.execute("SELECT * FROM Students")
+5L
El metodo execute se usa para ejecutar comandos SQL. Note que no hace falta agregar el ';' (punto y coma) al final del comando. Ahora es cuestion de recorrer el objeto cursor.
Cual metodo usar dependera de la cantidad de datos que tengamos, la memoria disponible en la PC y sobre todo, de como querramos hacerlo. Si estamos trabajando con datasets limitados, no habra problema con el uso de fetchall(), pero si la base de datos es lo suficientemente grande como para entrar en memoria, se podria implementar una estrategia como la que se encuentra aca:
-
importMySQLdb
-db=MySQLdb.connect(host="localhost",user="root",passwd="secret",db="PythonU")
-cursor=db.cursor()
-recs=cursor.execute("SELECT * FROM Students")
-forxinrange(recs):
-printcursor.fetchone()
+
importMySQLdb
+db=MySQLdb.connect(host="localhost",user="root",passwd="secret",db="PythonU")
+cursor=db.cursor()
+recs=cursor.execute("SELECT * FROM Students")
+forxinrange(recs):
+printcursor.fetchone()
O directamente:
-
importMySQLdb
-db=MySQLdb.connect(host="localhost",user="root",passwd="secret",db="PythonU")
-cursor=db.cursor()
-cursor.execute("SELECT * FROM Students")
-forrowincursor:
-printrow
+
importMySQLdb
+db=MySQLdb.connect(host="localhost",user="root",passwd="secret",db="PythonU")
+cursor=db.cursor()
+cursor.execute("SELECT * FROM Students")
+forrowincursor:
+printrow
Otro ejemplo basico de como hacerlo con PostgreSQL (similar al de MySQL). Se usó el esquema: CREATE TABLE estudiante ( nombre varchar, apellido varchar, fecha date, booleano bool, legajo serial PRIMARY KEY); Antes que nada se debe instalar el conector (para unix y windows).
Primero importar el conector y crear la conexión a la base de datos:
Luego crear un cursor para obtener los datos y ejecutar consulta:
-
>>>cur=conn.cursor()
->>>cur.execute("SELECT * FROM estudiante")
->>>rows=cur.fetchall()
->>>printrows
-
-[['Joe','Capbell',datetime.date(2006,2,10),False,1],['Joe','Doe',datetime.date(2004,2,16),False,2],['Rick','Hunter',datetime.date(2005,3,20),False,3],['Laura','Ingalls',datetime.date(2001,3,15),True,4],['Virginia','Gonzalez',datetime.date(2003,4,2),False,5]]
+
>>>cur=conn.cursor()
+>>>cur.execute("SELECT * FROM estudiante")
+>>>rows=cur.fetchall()
+>>>printrows
+
+[['Joe','Capbell',datetime.date(2006,2,10),False,1],['Joe','Doe',datetime.date(2004,2,16),False,2],['Rick','Hunter',datetime.date(2005,3,20),False,3],['Laura','Ingalls',datetime.date(2001,3,15),True,4],['Virginia','Gonzalez',datetime.date(2003,4,2),False,5]]
Algo más pitónico es crear el cursor simil diccionario (en vez de una lista de valores):
-
>>>cur=conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
->>>cur.execute("SELECT * FROM estudiante")
->>>forrowincur:# itero sober cada fila
->>># row es un diccionario, con las claves = nombres de campos
->>>print"Nombre y Apellido: %s, %s "%(row['nombre'],row['apellido'])
-
-NombreyApellido:Joe,Capbell
-NombreyApellido:Joe,Doe
-NombreyApellido:Rick,Hunter
-NombreyApellido:Laura,Ingalls
-NombreyApellido:Virginia,Gonzalez
+
>>>cur=conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
+>>>cur.execute("SELECT * FROM estudiante")
+>>>forrowincur:# itero sober cada fila
+>>># row es un diccionario, con las claves = nombres de campos
+>>>print"Nombre y Apellido: %s, %s "%(row['nombre'],row['apellido'])
+
+NombreyApellido:Joe,Capbell
+NombreyApellido:Joe,Doe
+NombreyApellido:Rick,Hunter
+NombreyApellido:Laura,Ingalls
+NombreyApellido:Virginia,Gonzalez
Nota: esto es propio del conector psycopg2. Igualmente otros conectores tambien lo soportan o se puede imitar (leyendo el atributo description del cursor que tiene la información de los campos):
Pregunta: Hola chicos. Estoy con un inconveniente que no puedo solventar. Tengo una funcion de python que genera unos querystrings para postgres.
Mi problema empieza cuando, por ejemplo hay uno de esos apellidos que tienen ', Ej: D'agostino
como resultado me queda el string (ejemplo)
-
'insert into personas (apellido) values ("D'agostino")'
+
'insert into personas (apellido) values ("D'agostino")'
Respuesta:
Lo que tendrías que hacer es que postgres te escapee automaticamente los valores, usando los parámetros de db-api (segúndo argumento del metodo execute del cursor):
-
cur=conn.cursor()
-cur.execute("insert into personas (apellido) values (%s)",["D'agostino"])
+
cur=conn.cursor()
+cur.execute("insert into personas (apellido) values (%s)",["D'agostino"])
Así, automáticamente postgres sabe, según el tipo de datos del parámetro, en este caso un string = "D'agostino", como escapear y formatear el sql para que no de error.
Además, esto es mas seguro frente a ataques por "inyección de sql", porque el formateo es automático, en vez de usar directamente el operador % sobre el query y pasarselo cocinado a la base.
Para hacerlo más robusto, podrías usar diccionario con los parametros (es más seguro en el caso que tengas varios parámetros, para evitar errores):
-
cur.execute("insert into personas (apellido) values (%(apellido)s)",{"apellido":"D'agostino"})
+
cur.execute("insert into personas (apellido) values (%(apellido)s)",{"apellido":"D'agostino"})
Igualmente, esto dependerá de las capacidades de cada conector (consultar variable paramstyle del módulo conector), pudiendo utilizarse los siguientes estilos de parametros:
diff --git a/deretiroacordoba/index.html b/deretiroacordoba/index.html
index 822bcbd17..b73e57e08 100644
--- a/deretiroacordoba/index.html
+++ b/deretiroacordoba/index.html
@@ -54,7 +54,7 @@
h">
-
+
Ir al contenido principal
@@ -88,12 +88,12 @@
diff --git a/edupython/index.html b/edupython/index.html
index 86f57f3f7..b378ed786 100644
--- a/edupython/index.html
+++ b/edupython/index.html
@@ -30,7 +30,7 @@
"Recordad que para poder modificar la wiki y po'>
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/emilianodallaverdemarcozzi/index.html b/emilianodallaverdemarcozzi/index.html
index 928c8e107..1a9da259b 100644
--- a/emilianodallaverdemarcozzi/index.html
+++ b/emilianodallaverdemarcozzi/index.html
@@ -27,7 +27,7 @@
Un poco sobre mi:
En el 2007 conocí Pyth">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/enlosmedios/index.html b/enlosmedios/index.html
index c181b2237..3670aece8 100644
--- a/enlosmedios/index.html
+++ b/enlosmedios/index.html
@@ -26,7 +26,7 @@
Reportaje sobre CDPedia a Facundo Batista FM La Tribu, 20 Enero 2010.
Juegos en el iPhone con sello nac">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013encordobacapital/index.html b/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013encordobacapital/index.html
index 60602cc91..f73e0fe45 100644
--- a/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013encordobacapital/index.html
+++ b/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013encordobacapital/index.html
@@ -26,7 +26,7 @@
Duración: 2 a 3 días
Lugar: UCC sede centro (preconfirmada); FAMAF-UNC (interesada); Centro de Convenciones en zona centrica (como plan de contingencias) ">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013enrosario/index.html b/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013enrosario/index.html
index c7529221a..0c07fd6c0 100644
--- a/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013enrosario/index.html
+++ b/eventos/Conferencias/ProcesoSeleccion/propuestadepycon2013enrosario/index.html
@@ -26,7 +26,7 @@
Estamos en el centro del país y contamos con una amplia red de transportes http://www.rosario.gov.ar/sitio/caracteristicas/geografica2.jsp?nivel=Ciudad&ult=Ci_2
Las autopistas a Buen">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/eventos/Conferencias/PyConAr2016/viaje/index.html b/eventos/Conferencias/PyConAr2016/viaje/index.html
index 73f22d9fc..78795d11b 100644
--- a/eventos/Conferencias/PyConAr2016/viaje/index.html
+++ b/eventos/Conferencias/PyConAr2016/viaje/index.html
@@ -30,7 +30,7 @@
Manuel Kaufmann (humitos): No tengo auto. Llego el Miércoles 23 de Noviembre a Bs As a las 18:30hs
Johanna Sanchez (ellaquimica">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/eventos/Conferencias/PyConAr2018/propuestasedecaba/index.html b/eventos/Conferencias/PyConAr2018/propuestasedecaba/index.html
index d6bb94af7..26480ca0f 100644
--- a/eventos/Conferencias/PyConAr2018/propuestasedecaba/index.html
+++ b/eventos/Conferencias/PyConAr2018/propuestasedecaba/index.html
@@ -29,7 +29,7 @@
¿Por qué en CABA?
La primer PyCo">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/eventos/Conferencias/PyConAr2020/propuestaejemplo/index.html b/eventos/Conferencias/PyConAr2020/propuestaejemplo/index.html
index 6b2664fb1..ad5be0dd7 100644
--- a/eventos/Conferencias/PyConAr2020/propuestaejemplo/index.html
+++ b/eventos/Conferencias/PyConAr2020/propuestaejemplo/index.html
@@ -27,7 +27,7 @@
¿Por qué en Algún Lado Re Copado?
Explicar por qué estaría bueno que el evento ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/eventos/Conferencias/procesoseleccion/index.html b/eventos/Conferencias/procesoseleccion/index.html
index 7eb2afbdb..daf08e36c 100644
--- a/eventos/Conferencias/procesoseleccion/index.html
+++ b/eventos/Conferencias/procesoseleccion/index.html
@@ -34,7 +34,7 @@
Pycon 2013 en Cordoba Capital
Pycon 2013 en Rosario">
-
+
Ir al contenido principal
@@ -68,12 +68,12 @@
diff --git a/eventos/Conferencias/pycon2006/index.html b/eventos/Conferencias/pycon2006/index.html
index 53b7c4faa..c19827c77 100644
--- a/eventos/Conferencias/pycon2006/index.html
+++ b/eventos/Conferencias/pycon2006/index.html
@@ -28,7 +28,7 @@
Empresas que están usando Pyt">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/eventos/Conferencias/pyconar2013/index.html b/eventos/Conferencias/pyconar2013/index.html
index 92afe48e8..77bbb0b7f 100644
--- a/eventos/Conferencias/pyconar2013/index.html
+++ b/eventos/Conferencias/pyconar2013/index.html
@@ -28,7 +28,7 @@
La conferencia se hizo! Tuvimos muy buenas k">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/eventos/PyCamp/2012/index.html b/eventos/PyCamp/2012/index.html
index 5e15432ab..5e7f11d3c 100644
--- a/eventos/PyCamp/2012/index.html
+++ b/eventos/PyCamp/2012/index.html
@@ -27,7 +27,7 @@
Fecha: Sabado 28/4 arrancando a la matina hasta el Martes 1/5 hasta las 17 pm aprox
Hay Internet: Si, por wi">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/eventos/PyDay/2011/Cordoba/comunidadanarquiasubversion/index.html b/eventos/PyDay/2011/Cordoba/comunidadanarquiasubversion/index.html
index 8b2c56fde..d2a06ba9d 100644
--- a/eventos/PyDay/2011/Cordoba/comunidadanarquiasubversion/index.html
+++ b/eventos/PyDay/2011/Cordoba/comunidadanarquiasubversion/index.html
@@ -32,7 +32,7 @@
Pensamientos sobre nuestras comunidades, formas de organización en las distintas etapas de las mismas, y temas relacionados.
http://pyar.usla.org.ar/">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/eventos/PyDay/2011/Cordoba/pythonpilas/index.html b/eventos/PyDay/2011/Cordoba/pythonpilas/index.html
index c18de0897..35ce6d413 100644
--- a/eventos/PyDay/2011/Cordoba/pythonpilas/index.html
+++ b/eventos/PyDay/2011/Cordoba/pythonpilas/index.html
@@ -32,7 +32,7 @@
Pilas es un motor o biblioteca para hacer juegos de manera sencilla, orientado a principiantes y programadores.
http://pyar.usla.org.ar/pilas001.ogv">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/eventos/PyDay/2011/Cordoba/pythonsugaricaro/index.html b/eventos/PyDay/2011/Cordoba/pythonsugaricaro/index.html
index 374dd9783..d412457a2 100644
--- a/eventos/PyDay/2011/Cordoba/pythonsugaricaro/index.html
+++ b/eventos/PyDay/2011/Cordoba/pythonsugaricaro/index.html
@@ -31,7 +31,7 @@
Presentación de ICARO, un entorno de robotica educativa con software libre diseñado para la escuela inicial y media. implementacion de un modulo pytho">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/eventos/PyDay/2011/Cordoba/pythontests/index.html b/eventos/PyDay/2011/Cordoba/pythontests/index.html
index 9226fe293..bf9d43771 100644
--- a/eventos/PyDay/2011/Cordoba/pythontests/index.html
+++ b/eventos/PyDay/2011/Cordoba/pythontests/index.html
@@ -31,7 +31,7 @@
Todos conocemos y aceptamos la vital importancia de escribir tests para nuestras aplicaciones. Pero no todos efectivamente escribimos esas test suites">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/eventos/Reuniones/2004/reunion04/index.html b/eventos/Reuniones/2004/reunion04/index.html
index 46fa387cc..0e5eb459b 100644
--- a/eventos/Reuniones/2004/reunion04/index.html
+++ b/eventos/Reuniones/2004/reunion04/index.html
@@ -27,7 +27,7 @@
Sitio
Estuvimos de acuerdo en que la complejidad de Zope/Plone, al menos para la estructura actual del grupo, nos está trayendo algunas desventajas. No obstante, decid">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Definimos una cuestión administrativa que teníamos pendiente: ¿qué vamos a hacer con nuestra lista de correo? La decisión final es encontrar una lista que cumpla con nuestras expectativas (que pueda tener nuestro dominio y que tenga archivo) y migrar a ella. Pero antes, nada. Al respecto, yo me llevé como pendiente averiguar que características tienen las listas que puedo hostear en mi sitio.
Expuse Decimal. Estuvo muy interesante, porque nos poníamos a discutir sobre la curvatura del círculo, que los complejos tienen infinitos todo alrededor, sobre el pelo del gato y la quinta pata del huevo. ¡Y hasta les pude contar como usar el módulo! Realmente me encantó. Ah, de paso:
Definimos el tema del Primer Sprint PyAr: vamos a hacer el Administrador de Colas de Mensajes (nombre no oficial), con interfaces SMTP (mail), SMPP (SMSs o mensajes cortos) y MM7 (MMSs o mensajes multimedia). La primer reunión será el Jueves 27 de Enero en el mismo lugar que hicimos la reunión, ya que comenzaremos con el diseño del sistema, y no necesitamos más que papel, lápiz, y buenas ideas (y, por supuesto, cerveeeeza).
diff --git a/eventos/Reuniones/2005/reunion06/index.html b/eventos/Reuniones/2005/reunion06/index.html
index 2854e4318..b56a46634 100644
--- a/eventos/Reuniones/2005/reunion06/index.html
+++ b/eventos/Reuniones/2005/reunion06/index.html
@@ -25,7 +25,7 @@
-
+
Ir al contenido principal
@@ -59,12 +59,12 @@
diff --git a/eventos/Reuniones/2005/reunion08/index.html b/eventos/Reuniones/2005/reunion08/index.html
index e1a6bb5ac..590ac80fa 100644
--- a/eventos/Reuniones/2005/reunion08/index.html
+++ b/eventos/Reuniones/2005/reunion08/index.html
@@ -26,7 +26,7 @@
Sebastián: Viene de CafeLUG, trabaja en wxPython y Z">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/eventos/Reuniones/2006/reunion19/index.html b/eventos/Reuniones/2006/reunion19/index.html
index e6cdca754..af2f5f710 100644
--- a/eventos/Reuniones/2006/reunion19/index.html
+++ b/eventos/Reuniones/2006/reunion19/index.html
@@ -26,7 +26,7 @@
La Casa del Queso, Av. Corrientes 3587, entre Billinghurst y Sánchez de Bustamante, Cap. Fed. Estaríamos, en la parte del primer piso.
¿Cuando? A la salida de CafeConf, o sea, de 19:30hs (gmt-">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/eventos/Reuniones/2006/reunion20/index.html b/eventos/Reuniones/2006/reunion20/index.html
index 1c2d8b7a9..e2ebb8c47 100644
--- a/eventos/Reuniones/2006/reunion20/index.html
+++ b/eventos/Reuniones/2006/reunion20/index.html
@@ -29,7 +29,7 @@
Presentación de los integrantes
Presentacíon de cada integrante y actividad actual, a modo de conocernos">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/eventos/Reuniones/2008/reunion26/index.html b/eventos/Reuniones/2008/reunion26/index.html
index 74493d199..b76a3e455 100644
--- a/eventos/Reuniones/2008/reunion26/index.html
+++ b/eventos/Reuniones/2008/reunion26/index.html
@@ -39,7 +39,7 @@
Leo De Luca (N)
Lucas Deves">
-
+
Ir al contenido principal
@@ -73,12 +73,12 @@
diff --git a/eventos/Reuniones/2008/reunion30/index.html b/eventos/Reuniones/2008/reunion30/index.html
index 1e12e5bd8..76c542241 100644
--- a/eventos/Reuniones/2008/reunion30/index.html
+++ b/eventos/Reuniones/2008/reunion30/index.html
@@ -51,7 +51,7 @@
Juan Pablo Giménez">
-
+
Ir al contenido principal
@@ -85,12 +85,12 @@
diff --git a/eventos/Reuniones/2009/reunion36/index.html b/eventos/Reuniones/2009/reunion36/index.html
index 424ed8c9c..791ccc101 100644
--- a/eventos/Reuniones/2009/reunion36/index.html
+++ b/eventos/Reuniones/2009/reunion36/index.html
@@ -40,7 +40,7 @@
¿De qué se habló?
Les pido mil disculpas, pero estoy escribiendo esto 3 meses despues de la reunion 😕 asi q">
-
+
Ir al contenido principal
@@ -74,12 +74,12 @@
diff --git a/eventos/Reuniones/2009/reunion39/index.html b/eventos/Reuniones/2009/reunion39/index.html
index 967275137..3b0a758b1 100644
--- a/eventos/Reuniones/2009/reunion39/index.html
+++ b/eventos/Reuniones/2009/reunion39/index.html
@@ -29,7 +29,7 @@
Como hacer un thread de +150 mails hablando de Python (¿'is == is', o '== is =='?)
Como incentivar el crecimiento del ecosistema de Python">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/eventos/Reuniones/2010/reunion40/index.html b/eventos/Reuniones/2010/reunion40/index.html
index 942cca35d..2313fd34e 100644
--- a/eventos/Reuniones/2010/reunion40/index.html
+++ b/eventos/Reuniones/2010/reunion40/index.html
@@ -33,7 +33,7 @@
Los organizadores contaron sobre el lugar elegido, en que días se va a realizar, e hicie">
-
+
Ir al contenido principal
@@ -67,12 +67,12 @@
diff --git a/eventos/Reuniones/2010/reunion42/index.html b/eventos/Reuniones/2010/reunion42/index.html
index 7b71df497..b73195959 100644
--- a/eventos/Reuniones/2010/reunion42/index.html
+++ b/eventos/Reuniones/2010/reunion42/index.html
@@ -26,7 +26,7 @@
—¡Cuarenta y dos! —exclamó Loonquawl—. ¿Es eso todo lo que tienes que mostrar tras siete millones y medio de años de trabajo?
—Lo he comprobado muy minuciosamente —dijo el ordenad">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/eventos/Reuniones/2010/reunion45/index.html b/eventos/Reuniones/2010/reunion45/index.html
index 9eb8dbb82..ce82da5f6 100644
--- a/eventos/Reuniones/2010/reunion45/index.html
+++ b/eventos/Reuniones/2010/reunion45/index.html
@@ -30,7 +30,7 @@
PyAr y PyBar
Llamado por Colaboradores: Proyectos presentados en Conurbania">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/eventos/Reuniones/2010/reunion46/index.html b/eventos/Reuniones/2010/reunion46/index.html
index 2ab2b15f8..ff5ca8173 100644
--- a/eventos/Reuniones/2010/reunion46/index.html
+++ b/eventos/Reuniones/2010/reunion46/index.html
@@ -50,7 +50,7 @@
Minuta
El pasado jueves 23 de dici">
-
+
Ir al contenido principal
@@ -84,12 +84,12 @@
diff --git a/eventos/Reuniones/2011/reunion49/index.html b/eventos/Reuniones/2011/reunion49/index.html
index eef8619f9..72000ec5b 100644
--- a/eventos/Reuniones/2011/reunion49/index.html
+++ b/eventos/Reuniones/2011/reunion49/index.html
@@ -39,7 +39,7 @@
Organización de un pyDay en S">
-
+
Ir al contenido principal
@@ -73,12 +73,12 @@
diff --git a/eventos/Reuniones/2011/reunion50/index.html b/eventos/Reuniones/2011/reunion50/index.html
index d097a40ef..e54d33693 100644
--- a/eventos/Reuniones/2011/reunion50/index.html
+++ b/eventos/Reuniones/2011/reunion50/index.html
@@ -32,7 +32,7 @@
Promover Python en el sistema educativo
Debate: ¿Nos c">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/eventos/Reuniones/2012/reunion51/index.html b/eventos/Reuniones/2012/reunion51/index.html
index b2f78c9e3..67a467297 100644
--- a/eventos/Reuniones/2012/reunion51/index.html
+++ b/eventos/Reuniones/2012/reunion51/index.html
@@ -29,7 +29,7 @@
PyCon
Como darle un marco legal y de soporte administrativo a python argentina ">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/eventos/Reuniones/2012/reunion52/index.html b/eventos/Reuniones/2012/reunion52/index.html
index af37cb073..60d623766 100644
--- a/eventos/Reuniones/2012/reunion52/index.html
+++ b/eventos/Reuniones/2012/reunion52/index.html
@@ -30,7 +30,7 @@
PyCon: estado
Como darle un marco legal y de soporte administrativo a Python Argentina sin desvirtuar la actual'>
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/eventos/Reuniones/2012/reunion54/index.html b/eventos/Reuniones/2012/reunion54/index.html
index e04338216..8f85c2555 100644
--- a/eventos/Reuniones/2012/reunion54/index.html
+++ b/eventos/Reuniones/2012/reunion54/index.html
@@ -31,7 +31,7 @@
Pines de Android, New Relic y otras
Frisbees, helicoptercitos, ">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/eventos/Reuniones/2012/reunion56/index.html b/eventos/Reuniones/2012/reunion56/index.html
index 9b0eba09d..64536ad04 100644
--- a/eventos/Reuniones/2012/reunion56/index.html
+++ b/eventos/Reuniones/2012/reunion56/index.html
@@ -30,7 +30,7 @@
Actividades Sociales: ¡Fiesta!, Asado/Picnic y día turístico
Revisar el Ll">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/eventos/Reuniones/2014/reunion62/index.html b/eventos/Reuniones/2014/reunion62/index.html
index 1860238b4..680701b50 100644
--- a/eventos/Reuniones/2014/reunion62/index.html
+++ b/eventos/Reuniones/2014/reunion62/index.html
@@ -28,7 +28,7 @@
Juan Gabardini va a venir y nos va a contar la experiencia de pertenecer a SADIO (lo cual nos daría personería)
¿Está bien que PyAr ponga plata para proyectos de PyAr? ">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/eventos/Reuniones/2015/reunion65/index.html b/eventos/Reuniones/2015/reunion65/index.html
index 66be4e8ec..0e47d15e9 100644
--- a/eventos/Reuniones/2015/reunion65/index.html
+++ b/eventos/Reuniones/2015/reunion65/index.html
@@ -37,7 +37,7 @@
Minuta
Se charlon varios temas los pri">
-
+
Ir al contenido principal
@@ -71,12 +71,12 @@
diff --git a/eventos/Reuniones/2016/reunion66/index.html b/eventos/Reuniones/2016/reunion66/index.html
index 8f207d9b7..7ed22c455 100644
--- a/eventos/Reuniones/2016/reunion66/index.html
+++ b/eventos/Reuniones/2016/reunion66/index.html
@@ -37,7 +37,7 @@
Minuta
Se charlaron varios temas, los p">
-
+
Ir al contenido principal
@@ -71,12 +71,12 @@
diff --git a/eventos/Sprints/olpcserver/index.html b/eventos/Sprints/olpcserver/index.html
index 5d25660e5..a785b2fe3 100644
--- a/eventos/Sprints/olpcserver/index.html
+++ b/eventos/Sprints/olpcserver/index.html
@@ -29,7 +29,7 @@
veamos que módulos sería mas útil y pode">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/eventos/conferencias/index.html b/eventos/conferencias/index.html
index add19c0e1..b166c7d11 100644
--- a/eventos/conferencias/index.html
+++ b/eventos/conferencias/index.html
@@ -28,7 +28,7 @@
Pycon Argentina 2016, realizada los días 25, 26 y 27 de Noviembre - Bahía Blanca.
PyCon Argentina 2015, rea">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/eventos/index.html b/eventos/index.html
index 73063d508..91b228baf 100644
--- a/eventos/index.html
+++ b/eventos/index.html
@@ -28,7 +28,7 @@
Eventos
En PyAr planeamos cuatro tipos de eventos">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/extraermails/index.html b/extraermails/index.html
index 01ca4854c..b4a7a6ea8 100644
--- a/extraermails/index.html
+++ b/extraermails/index.html
@@ -29,7 +29,7 @@
El código anterior devuelve una lista de strings, donde cada string es una ">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
El código anterior devuelve una lista de strings, donde cada string es una dirección de email. El texto original puede contener basura como espcios, comas u otros caracteres.
Autor
diff --git a/ezequielmarquez/index.html b/ezequielmarquez/index.html
index 3a6ae6b02..2a209f495 100644
--- a/ezequielmarquez/index.html
+++ b/ezequielmarquez/index.html
@@ -26,7 +26,7 @@
Web Site
Twitter">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/foro_y_redes/index.html b/foro_y_redes/index.html
index 8f4e06264..fde85773c 100644
--- a/foro_y_redes/index.html
+++ b/foro_y_redes/index.html
@@ -27,7 +27,7 @@
Está basado en Discourse, así que se puede utilizar como foro puro,
pero tambi">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/gastemosla/index.html b/gastemosla/index.html
index f824b007e..bcd04e6c8 100644
--- a/gastemosla/index.html
+++ b/gastemosla/index.html
@@ -28,7 +28,7 @@
Pagar para mejorar algunas cosas institucionales de PyAr (i.e.: mejora del frontArpage de PyAr)
Imprimir tutor">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/gonzalodelgado/index.html b/gonzalodelgado/index.html
index 3635b8cd4..e026f8cea 100644
--- a/gonzalodelgado/index.html
+++ b/gonzalodelgado/index.html
@@ -26,7 +26,7 @@
Soy Programador Universitario de la Facultad de Ciencias Exactas y Tecnología de la UNT
Trabajé en Fortix desde el año 2006 hasta el año 2009 como sysadmin. Es allí ">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/howtoconferencia/index.html b/howtoconferencia/index.html
index 2c3fcd3c0..943001c52 100644
--- a/howtoconferencia/index.html
+++ b/howtoconferencia/index.html
@@ -27,7 +27,7 @@
How to… or backstage about I Jornada Python Santa Fe
PyCon Argentina 2009, ¡termi">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/index.html b/index.html
index f71ed6fae..a66f19e75 100644
--- a/index.html
+++ b/index.html
@@ -37,7 +37,7 @@
Foro y Redes
Información sobre el foro (nuestro principal canal de com">
-
+
Ir al contenido principal
@@ -71,12 +71,12 @@
diff --git a/invitacioncuentawave/index.html b/invitacioncuentawave/index.html
index e26e798c8..9b4d46f58 100644
--- a/invitacioncuentawave/index.html
+++ b/invitacioncuentawave/index.html
@@ -26,7 +26,7 @@
Esta lista es para hacer una petición mas "ordenada" de las personas que quieren invitaciones para Google WAVE
Escribí tu nombre acá y pronto te harán lle'>
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/joaquinsorianello/index.html b/joaquinsorianello/index.html
index db87f3a55..5118e619d 100644
--- a/joaquinsorianello/index.html
+++ b/joaquinsorianello/index.html
@@ -28,7 +28,7 @@
Soy desarrollador de software autodidacta y me gusta trabajar en areas que van del arte programatico a los sistemas de alta disponibilidad.
Naci en Bariloche, actualm">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/johnlenton/index.html b/johnlenton/index.html
index 0155799d2..d76074112 100644
--- a/johnlenton/index.html
+++ b/johnlenton/index.html
@@ -26,7 +26,7 @@
|http://except.com.ar/| Soy uno de los fundadores de GrULiC (el grupo de usuarios de software libre de Córdoba)
|http://www.vialibre.org.">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/juanjociarlante/index.html b/juanjociarlante/index.html
index 7244be94c..c59a46a31 100644
--- a/juanjociarlante/index.html
+++ b/juanjociarlante/index.html
@@ -26,7 +26,7 @@
Soy apasionado del Software Libre desde '93, cuando booteé por primera vez un Yggdrasil en mi 386 (partidura-de-cabeza si las hay...).
Mi primer">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/juanjoconti/index.html b/juanjoconti/index.html
index 85931b336..d0cb782e8 100644
--- a/juanjoconti/index.html
+++ b/juanjoconti/index.html
@@ -27,7 +27,7 @@
Juanjo Conti
Soy ingeniero de la FRSF-UTN, trabajo en una empresa de telecomunicaciones y tengo una beca de la UTN para investigar y realizar una maestría. Uso Python hace 4 años. Tengo un bl">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/juegos/worldst/index.html b/juegos/worldst/index.html
index 2f8679af7..774f8d9de 100644
--- a/juegos/worldst/index.html
+++ b/juegos/worldst/index.html
@@ -29,7 +29,7 @@
history by lucio
trivia by">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/listab/index.html b/listab/index.html
index 586b5f598..dc02944dd 100644
--- a/listab/index.html
+++ b/listab/index.html
@@ -27,7 +27,7 @@
||'''Batteries Included?''' || [[Rating(BatteriesIncluded)]] ||
||'''How Does It Make You Feel?'''">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/listadecorreo/index.html b/listadecorreo/index.html
index bdd6fc645..aa0b4ca71 100644
--- a/listadecorreo/index.html
+++ b/listadecorreo/index.html
@@ -27,7 +27,7 @@
Está basado en Discourse, así que se puede utilizar como foro puro,
pero tambi">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/llamadoasedepyconar2012/index.html b/llamadoasedepyconar2012/index.html
index b1ec11e79..09bdb5487 100644
--- a/llamadoasedepyconar2012/index.html
+++ b/llamadoasedepyconar2012/index.html
@@ -26,7 +26,7 @@
Estimados pythoner@s, los invitamos a proponerse ustedes y a su ciudad como la posible sede de la próxima Pycon Argentina.
Vamos a recibir propuestas hasta el 15 de No">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/marcelofernandez/index.html b/marcelofernandez/index.html
index ec37b58f4..00369465f 100644
--- a/marcelofernandez/index.html
+++ b/marcelofernandez/index.html
@@ -27,7 +27,7 @@
Email: marcelo.fidel.fernandez AT SPAMFREE gmail DOT com
Pueden encontrar experimentos, comentarios, investigación, en mi blog">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/marcosdione/index.html b/marcosdione/index.html
index 7e20ad9a9..4a82e3a88 100644
--- a/marcosdione/index.html
+++ b/marcosdione/index.html
@@ -26,7 +26,7 @@
Soy de Córdoba, Córdoba (una es la ciudad, la otra la provincia, en ese orden, no vayan a confundir). Licenciado en Cs. de la Computación, FaMAF, UNC, 2004.
Llev">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/marianogarcia/index.html b/marianogarcia/index.html
index 83f454855..8ef174e58 100644
--- a/marianogarcia/index.html
+++ b/marianogarcia/index.html
@@ -26,7 +26,7 @@
Email: garcia.berrotaran AT SPAMFREE gmail DOT com
Vivo en Córdoba Actualmente trabajo como Web Developer. En la oficina programo en PHP / Javascript / Java y en mi casa en Python.">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/marianomara/index.html b/marianomara/index.html
index 878200966..7fc57cc8a 100644
--- a/marianomara/index.html
+++ b/marianomara/index.html
@@ -31,7 +31,7 @@
Empecé con Python en 2007, educandome con mucha lectura y algo de prá">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/martinchikilian/index.html b/martinchikilian/index.html
index 98c28fd54..40cf8926a 100644
--- a/martinchikilian/index.html
+++ b/martinchikilian/index.html
@@ -26,7 +26,7 @@
Email: martin.chikilian AT SPAMFREE gmail DOT com You can even more obfuscate your email address by adding more uppercase letters followed by a leading and trailing blank.
Hac">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/material/index.html b/material/index.html
index 1bf45d897..897f49fa0 100644
--- a/material/index.html
+++ b/material/index.html
@@ -30,7 +30,7 @@
Folletos
De uso general 01 (por Cesar '>
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/matiasgieco/index.html b/matiasgieco/index.html
index a12f8a851..073c31446 100644
--- a/matiasgieco/index.html
+++ b/matiasgieco/index.html
@@ -27,7 +27,7 @@
Soy Matías Gieco, nacido bajo el mes de virgo allá por el 77. ¿Qué hago? Poco y nada.
En la lista de PyA">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Estoy en LinkedIn, en los grupos de python y PyAr, porque da chapa de que se algo.
Si quieren algún otro usuario y contraseña de algún otro servicio, manden un email a la dirección escrita y se las doy, total quien va a romper lo que no es suyo.
-
deftiempo_de_vida(fecha_nac):
-hoy=datetime.date.today()
-return(hoy-fecha_nac)
-
-nac_bb=datetime.date(2008,04,15)
-nac_bullie=datetime.date(2008,04,15)-datetime.timedelta(366)# si, un año justo justo!
+
deftiempo_de_vida(fecha_nac):
+hoy=datetime.date.today()
+return(hoy-fecha_nac)
+
+nac_bb=datetime.date(2008,04,15)
+nac_bullie=datetime.date(2008,04,15)-datetime.timedelta(366)# si, un año justo justo!
diff --git a/mauricio-josc3a920tobares/index.html b/mauricio-josc3a920tobares/index.html
index eb7687455..74ed53f48 100644
--- a/mauricio-josc3a920tobares/index.html
+++ b/mauricio-josc3a920tobares/index.html
@@ -27,7 +27,7 @@
## You can even more obfuscate your email address by adding more uppercase letters followed by a leading and trailing blank.
Mi">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/mauricioferrari/index.html b/mauricioferrari/index.html
index 8c342731a..23570a0a4 100644
--- a/mauricioferrari/index.html
+++ b/mauricioferrari/index.html
@@ -26,7 +26,7 @@
*use otras cosas que me aburren como vb, me hicieron padecer como C*
*alguna vez me interese con smalltalk pero no">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/mensajesexcepcionales/index.html b/mensajesexcepcionales/index.html
index c947f11cf..ab836af83 100644
--- a/mensajesexcepcionales/index.html
+++ b/mensajesexcepcionales/index.html
@@ -26,7 +26,7 @@
Esta página busca ser una guía para las personas que se estén iniciando en este maravilloso lenguaje y se encuentren con erro'>
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
En Python es fundamental dejar sangría (espacio antes de las instrucciones), que identifica el bloque al que pertenece, ya que no usamos llaves o palabras clave para delimitar los bloques como en otros lenguajes. Si bien esto ayuda a escribir código más prolijo evitando errores de anidación, puede ser raro hasta que uno se acostumbra.
Generalmente, cada vez que abramos un bloque (con una sentencia que termina en : -dos puntos- ), debemos incrementar la sangría. Por ej:
-
defmayor(param1,param2=0):
-ifparam1isNone:
-return"El valor es None=Nulo! :S"
-elifparam1>param2:
-printparam1,"es mayor a",param2
-return"todo bien :)"
-else:
-printparam1,"es menor a",param2
-return"todo mal :("
-
-printmayor(5)
+
defmayor(param1,param2=0):
+ifparam1isNone:
+return"El valor es None=Nulo! :S"
+elifparam1>param2:
+printparam1,"es mayor a",param2
+return"todo bien :)"
+else:
+printparam1,"es menor a",param2
+return"todo mal :("
+
+printmayor(5)
Que puede pasar si no lo hacemos...
Error de Sangría: se esperaba un bloque con sangría
Aquí el print esta a la misma altura que el if (sin sangría), cuando deberíamos haber dejado el espacio correspondiente porque estamos abriendo un nuevo bloque con :
Aquí el print "..."no esta a la misma altura que el if False ni que el pass ni que el def, por lo que no se sabe a que bloque pertenece. Si cerramos el bloque del if debería estar a la misma altura que este, y si pertenece al bloque if, debería estar dentro de este a la altura del pass. Si el print no pertenece a la función, deberíamos ponerlo a la misma altura que el def
Errores de Sintaxis (SyntaxError)
@@ -256,71 +256,71 @@
Mensajes Excepcionales
Esperando no haberlo abrumado con el resumen de la sintaxis del lenguaje (los interesados pueden ver la especificación completa en http://docs.python.org/), veamos que pasa si no la respetamos:
Python respeta mayúsculas y minusculas, If no es el if que queremos usar. Tener cuidado sobre todo si venimos de lenguajes que son indiferentes a este tema (por. ej. Visual Basic)
La asignación no se puede usar en una expresión (comparación), por ej., para evitar los errores clásicos en C while(v=1)... donde nos asignaba 1 a v en vez de comparar si v era igual a 1. En este caso, usar el operador de comparación while a==1:
Las cadenas simples (de una sola línea) deben empezar y terminar en la misma línea y con el mismo caracter, comillas (") o tilde (').
Error de Sintaxis: FinDeArchivo mientras se buscaba una cadena de "múltiples líneas"
-
>>>"""
-... mucho
-... texto
-...
-SyntaxError: EOF while scanning triple-quoted string
+
>>>"""
+... mucho
+... texto
+...
+SyntaxError: EOF while scanning triple-quoted string
Las cadenas de múltiples líneas, deben empezar con triple comilla o tilde, y terminar con lo mismo. Aquí faltó cerrar la cadena con """ Nota: el error es simulado, es difícil que suceda en el intérprete, pero si ocurre en un archivo)
Error de Sintaxis: no es posible asignar a un operador
-
>>>numero+antiguo=1
-File"<input>",line1
-SyntaxError:can't assign to operator (<input>, line 1)
+
>>>numero+antiguo=1
+File"<input>",line1
+SyntaxError:can't assign to operator (<input>, line 1)
El nombre de la variable es inválido, sería: numero_mas_antiguo=1
El compilador de Python es muy estricto, y si no recibe el símbolo/componente léxico correcto ("token") nos emitirá estos errores. En este caso, se debe a que los numeros que comienzan con 0 es un caso especial de notación octal (base 8), por lo que solo acepta números del 0 al 7. Para corregir el error, eliminar el 0 que precede al número print 8
Errores de Nombres (NameError)
@@ -331,43 +331,43 @@
Mensajes Excepcionales
O sea, previamente debimos haberle asignado un valor a una variable (con =), definido una función con def o clase con class. Tener en cuenta que Python justamente es dinámico, y si el interprete no pasa por la linea de la definición, no se define, por más que este el código en el archivo.
En otros lenguajes, si la variable no esta definida, a veces toma un valor arbitrario (nulo, 0 o cadena vacia) o queda declarada sin inicializar (tomando cualquier valor que esté en la memoria), con los consiguientes errores que esto puede ocasionar. Para prevenir esto, en Python es necesario explicitamente definir ("inicializar") la variable con un valor inicial.
Error de Nombre: el nombre 'variable' no está definido
Estamos queriendo usar un nombre (identificador) de algo que no existe. En este caso la variable Saludo no está inicializada, ya que el nombre de variable correcta es saludo (notar la diferencia de mayúsculas y minúsculas que comentamos en la sección anterior)
Error de Nombre: el nombre global 'variable' no está definido
Similar al anterior, estamos queriendo usar una variable que no definimos previamente (ahora dentro de una función). O definimos la variable globalmente (fuera de la función), o localmente (dentro de la función).
Error de no vinculación local: la variable local 'xxx' fue referenciada antes de asignarla
Una variación del anterior, pero en este caso, debemos usar la sentencia global variable dentro de la función, ya que, sinó, al asignarle un valor dentro de la función, se convierte automáticamente en una variable local, por más que exista globalmente (y da error si la asignación no está al principio de la función antes de usar la variable):
Si si, Python es fuertemente tipado, en general no hará mágia con nuestros datos para convertirlos de un tipo a otro, si no se lo pedimos explícitamente.
No como en otros lenguajes, que cambiarían el tipo de una variable silenciosamente dependiendo del contexto (que puede ser ambiguo, por ej. ¿convertir a float o int?) con el consiguiente arrastre de un error difícil de solucionar.
Error de Tipo: tipo de operando no soportado para +: 'int' y 'str'
Típico, en algunos lenguajes esto puede resultar "510" o 15 (dependiendo como entienda el contexto, el órden de los operandos, etc.) ya que hacen una conversión de tipos implícita.
En Python, gentilmente nos avisa que, explicitamente debemos convertir el número a cadena (str(a)+b que resulta en "510") o la cadena en número (a+int(b) que resulta en 15.
Para iterar (recorrer uno a uno los elementos de una secuencia o colección), por ej. en un for, es necesario que esta sea realmente una secuencia o iterable (tuplas, listas, diccionario, conjunto, etc.)
Funciones
Podemos tener errores de tipo o de sintaxis respecto a las funciones, por ejemplo:
Estamos queriendo llamar a una variable que tiene un entero, cosa que no se puede (no es una "función llamable"). Seguramente, o la variable no debería haber sido un entero, o en vez de llamarla deberíamos aplicar algún operador o método sobre ella.
Error de Tipo: función() toma al menos un argumento (0 dados)
Al definir la función, dijimos que tenía dos parámetros (param1 y param2=0). Salvo que el parámetro tenga un valor por defecto (en el caso de param2 es 0), debemos pasarlo al llamar a la función. Revisar...
Error de Tipo: función() toma como mucho 2 argumentos (3 dados)
En este caso '10ab', salvo que las letras sean un error te escritura, estamos intentando convertir un valor hexadecimal (base 16) a entero, sin especificarlo, por lo que intenta base 10 por defecto. Lo correcto sería int("10ab",16)
Igualmente siempre es conveniente capturar este tipo de errores, para validar que el dato a convertir es realmente un número, y sinó, tomar una medida adecuada.
Error de Valor: literal inválido para float() con base 10: 'xxxx'
Lo mismo que el anterior, pero con la salvedad que para python debemos indicar los decimales con el punto (.) y no la coma (,). Podríamos convertirlo facilmente: float("10,50".replace(",",".")
Error de Valor: el día esta fuera de rango para el mes
En Python, podemos asignar varios elementos a una lista de destinos, pero la cantidad de destinos y de elementos a asignar deben coincidir. En este caso, a=1, b=2, c=3 y al cuarto elemento ya no hay a que asignarlo. Podríamos agregar un destino más: a,b,c,d = (1,2,3,4) o sacar un elemento a asignar de la expresión: a,b,c = (1,2,3).
Error de Valor: necesita más de 2 valores para desempaquetar
Caso inverso al anterior, nos falta un elemento en la expresión de asignación (o nos sobra un destino). Posible solución: sacamos un destino x,y = 1, 2 o agregamos un elemento: x,y,< = 1, 2 ,3
En los strings (cadenas), ciertos caracteres tienen un significado especial. Es el caso de la barra invertida (""), que identifica que lo que sigue definie un caractér especial ("n" para el salto de linea, "xfe" para el caracter cuyo código hexadecimal es FE, etc.) Si queremos una barra invertida (por ejemplo, en un directorio de windows), debemos usar strings crudos (raws): r"C:xaraza.txt" o doble barra invertida: "C:\xaraza.txt"
Errores de Atributos (AttributeError)
Practicamente todo en Python es un objeto, y estos objetos tienen métodos y "propiedades" (ambos denominados atributos). Si intentamos acceder a un atributo que no pertenece al objeto, se producirá uno de los siguientes errores:
Error de Atributo: el objeto 'NoneType' no tiene el atributo 'split'
En este caso estamos queriendo invocar a un método split que no esta definido para este tipo de objeto (aquí None, pero podría ser cualquier otro). Seguramente la variable fecha debería ser otra cosa, o nos equivocamos de método a invocar.
Error de Atributo: el objeto 'modulo' no tiene el atributo 'next'
Similar al anterior, pero en este caso estamos importando un módulo csv que no tiene la función next}. En este caso particular, next es un método de la instancia de csv_reader, no del módulo.
Errores de Índice (IndexError)
Error de Índice: el índice de lista esta fuera de rango
En este caso, podríamos acceder al valor de correcto usando dict['clave'] que sí existe, o pedir dict.get('clave2') que si la clave no existe, devolverá None y no producirá una excepción.
Otros Errores
Los errores del sistema operativo y bibliotecas relacionadas también se expresan como excepciones:
IOError: [Errno 2] No existe el archivo o directorio: 'C:\saraza'
El archivo solicitado no existe, si queremos crearlo deberíamos pasarle un segundo parámetro que lo especifique: open("saraza","a") o open("saraza","w")
Advertencias
Como comentabamos, hay Excepciones que no son errores, sino advertencias. Se usan para avisarnos sobre algún cambio en el lenguaje o código potencialmente incorrecto o perjudicial:
Advertencia de "Deprecación": el módulo md5 esta desaconsejado; use en su lugar haslib
En esta versión de Python, el módulo md5 existe por compatibilidad hacia atrás. En versiones posteriores podría no existir más. Se recomienda revisar la recomendación que nos da Python: el módulo hashlib.
diff --git a/merchandisingpyconar2011/index.html b/merchandisingpyconar2011/index.html
index 908631f06..1e45b3a09 100644
--- a/merchandisingpyconar2011/index.html
+++ b/merchandisingpyconar2011/index.html
@@ -26,7 +26,7 @@
Para Pyconar 2011 vamos a hacer que elijas uno de los regalos ( seran varios ? ) que te gustaría llevarte del evento.
¿ Te gusta el merc">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/miembros/gilgamezh/index.html b/miembros/gilgamezh/index.html
index 3c0000f27..74c2d8fff 100644
--- a/miembros/gilgamezh/index.html
+++ b/miembros/gilgamezh/index.html
@@ -26,7 +26,7 @@
Blog: http://gilgamezh.me/blog
Actualmente vivo en CABA y trabajo en sistemas desde el Y2K. Sysadmin/WebOps/SRE/etc. Estudiante truncado de Sistemas. Me gusta mucho tra">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/miembros/mmartinovic/index.html b/miembros/mmartinovic/index.html
index 9a1b1f741..0a625155e 100644
--- a/miembros/mmartinovic/index.html
+++ b/miembros/mmartinovic/index.html
@@ -26,7 +26,7 @@
Soy desarrollador python desde el año 2009.
He trabajado con WxPython, QT, Flask... pero realmente me encanta laburar con Django.">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/minifaq/index.html b/minifaq/index.html
index ca9f23e69..39e0ba597 100644
--- a/minifaq/index.html
+++ b/minifaq/index.html
@@ -31,7 +31,7 @@
¿Cuales son los interpretes que puedo usar?
¿Com">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/nickar/index.html b/nickar/index.html
index 8da982d3c..7074c36c5 100644
--- a/nickar/index.html
+++ b/nickar/index.html
@@ -26,7 +26,7 @@
TODO:Hablar sobre mi.
Email: np AT SPAMFREE cs DOT uns DOT edu DOT ar">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/nicolasdemarchi/index.html b/nicolasdemarchi/index.html
index 981c31127..c9b748e86 100644
--- a/nicolasdemarchi/index.html
+++ b/nicolasdemarchi/index.html
@@ -26,7 +26,7 @@
Blog: http://gilgamezh.me/blog
Actualmente vivo en CABA y trabajo en sistemas desde el Y2K. Sysadmin/WebOps/SRE/etc. Estudiante truncado de Sistemas. Me gusta mucho tra">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/noticias/index.html b/noticias/index.html
index fac85f899..04b3126a5 100644
--- a/noticias/index.html
+++ b/noticias/index.html
@@ -34,7 +34,7 @@
Python Argentina participará con un '>
-
+
Ir al contenido principal
@@ -68,12 +68,12 @@
diff --git a/obteniendorespuestas/index.html b/obteniendorespuestas/index.html
index 6d5bd0372..27e4c620c 100644
--- a/obteniendorespuestas/index.html
+++ b/obteniendorespuestas/index.html
@@ -27,7 +27,7 @@
Nota del Traductor
En el texto se utiliza varias veces la abreviación "RTFM!", que traducida significa "lee el maldito manual!"(Read The Fucking Manual!'>
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Los tipos compuestos pueden ser devueltos como secuencias (tuplas o listas), diccionarios u objetos. En este ejemplo se devuelve un tipo compuesto representando una persona:
Cuando una función plpython es usada en un disparador, el diccionario TD contiene:
@@ -197,28 +197,28 @@
Pl/python: Python Dentro De Postgresql
Adicionalmente, el módulo plpy provee dos funciones: execute y prepare.
Llamar a plpy.execute(query, limit) con una consulta (query: string) y un límite de registros opcional (limit), permite ejecutar la consulta y devuelve los resultados en un objeto que emula una lista de diccionarios, pudiendo acceder por número de fila y nombre de columna. Tiene tres métodos adicionales: nrows que devuelve el número de filas, y status.
Ejemplo:
-
rv=plpy.execute("SELECT * FROM mi_tabla",5)
-forfilainrv:
-printfila['columna']
+
rv=plpy.execute("SELECT * FROM mi_tabla",5)
+forfilainrv:
+printfila['columna']
La función plpy.prepare(query,[parameter_types]), prepara el plan de ejecución para una consulta, se le pasa la consulta como string y la lista de tipos de parámetros:
-
plan=plpy.prepare("SELECT apellido FROM usuario WHERE nombre = $1 AND casado = $2 ",["text","boolean"])
+
plan=plpy.prepare("SELECT apellido FROM usuario WHERE nombre = $1 AND casado = $2 ",["text","boolean"])
text y boolean son los tipos de la variables que se pasara como parámetros ($1 y $2).
Despues de preparar la sentencia, usar la función plpy.execute para ejecutarla:
-
rv=plpy.execute(plan,["Mariano",True],5)
+
rv=plpy.execute(plan,["Mariano",True],5)
Se pasa el plan como primer argumento, los parámetros como segundo (en este caso, busca nombre="Mariano" y si esta casado). El límite (tercer argumento) es opcional.
Al preparar un plan, este se almacena para usarlo posteriormente. Para usarlo eficazmente entre llamada y llamada, se debe usar un diccionario de almacenamiento persistente (SD o GD) para guardarlo:
diff --git a/preferenciasdelusuario/index.html b/preferenciasdelusuario/index.html
index e6946c1fb..0c8f42d9f 100644
--- a/preferenciasdelusuario/index.html
+++ b/preferenciasdelusuario/index.html
@@ -27,7 +27,7 @@
Si sigue el enlace de `[[GetText(Create Profile)]]`_, se le c">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Las celdas son como cajones donde se guarda una variable para que pueda ser manipulada dentro de generadores, funciones y clases internos (closures).
Técnicamente hablando, las funciones internas, clases, expresiones generadoras y demás pueden tener "variables libres" (ver ejemplos). Esas variables libres son las celdas, y se rellenan con un valor como cualquier variable - el chiste es que varios pedazos de código pueden apuntar a la misma celda (y por lo tanto modificar la misma variable).
Ejemplo:
-
deff(x):
-defg():
-returnx+1
-returng()
-# aquí "x" se incrementó, x no es local a 'g'
-# x es una celda en toda la función f
-# para que pueda ser accedida desde g y f a la vez
+
deff(x):
+defg():
+returnx+1
+returng()
+# aquí "x" se incrementó, x no es local a 'g'
+# x es una celda en toda la función f
+# para que pueda ser accedida desde g y f a la vez
Otro
-
deff(l):
-escala=sum(l)
-returnset(x/escalaforxinl)
-# escala es una celda porque "x / escala for x in l"
-# es una expresión generadora, y su única forma de
-# acceder a "escala" es a través de la celda
+
deff(l):
+escala=sum(l)
+returnset(x/escalaforxinl)
+# escala es una celda porque "x / escala for x in l"
+# es una expresión generadora, y su única forma de
+# acceder a "escala" es a través de la celda
Es importante saber cuáles de nuestras variables son celdas y cuáles simplemente locales, porque la sintaxis de Python nos prohíbe borrar celdas, no así variables locales:
-
deff(x):
-rv=set([i*xforiinxrange(10)])
-delx# bizarro pero ok
-returnrv
-
-defg(x):
-rv=set(i*xforiinxrange(10))
-delx# error de sintaxis, no se pueden borrar celdas
-returnrv
+
deff(x):
+rv=set([i*xforiinxrange(10)])
+delx# bizarro pero ok
+returnrv
+
+defg(x):
+rv=set(i*xforiinxrange(10))
+delx# error de sintaxis, no se pueden borrar celdas
+returnrv
Nótese que en f, x no es una celda porque ocurre en una expresión de lista por comprensión - que se parece, pero no es un generador.
La documentación de Python sólo menciona un scope lógico local, el "local". Tiene sentido, puesto que las variables son o locales, o globales, o celdas (ver pregunta anterior).
Las variables locales todos las conocemos:
-
deff():
-x=4# x es local
+
deff():
+x=4# x es local
Los parámetros de una función también son variables locales. Por ende, self, en una función de una instancia, es también una variable local.
Las variables globales todos las conocemos también:
-
llamadas=0
-
-deff():
-globalllamadas# llamadas es global
-llamadas+=1
+
llamadas=0
+
+deff():
+globalllamadas# llamadas es global
+llamadas+=1
Las variables globales son "locales al módulo". Dentro de otro módulo, habrá otras globales.
Las "más globales de las globales" serían las variables globales del módulo "builtin`*"*, puesto que cuando un nombre no se encuentra ni entre las locales ni entre las globales del módulo, se busca en el módulo :underline:`builtin.
@@ -270,26 +270,26 @@
Preguntasfrecuentes
Esas son "fastlocals".
Casi todas las variables locales que se declaren van a ser rápidas. La única forma que conozco de generar variables locales lentas es con import * (en el scope local de una función, lo que es muy poco común), o especificando un diccionario de locales con eval()
La forma de "declarar" una variable de este tipo es simplemente asignandole un valor:
-
deff(...):
-...
-x=5
-...
+
deff(...):
+...
+x=5
+...
Esto ya define a "x" como variable local rápida. Y ojo, tiene ese status en todo el bloque.
O sea que cosas como esta no van a funcionar:
-
deff():
-ifx!=3:
-...
-...
-x=5
+
deff():
+ifx!=3:
+...
+...
+x=5
¿Por qué no? Porque x es local incluso cuando se accede en 'x != 3', y a esa altura, nunca fue asignada. Muchos pensarían que python va a ir a buscar una variable global llamada 'x' - nop... no es así. La simple asignación a x la define implícitamente como variable local y no global. Si queremos que sea global (y que la asignación cambie el valor de la variable global), hay que hacer:
"is" no falla, compara si dos objetos son el mismo (no si son iguales).
En algunos casos, ofrece resultado que a primera vista sorprenden...
-
>>>a=3
->>>b=3
->>>aisb
-True
+
>>>a=3
+>>>b=3
+>>>aisb
+True
En este caso a apunta a un 3 en memoria, y b apunta al mismo 3 en memoria. Python no creó dos objetos "3", sino que usó el mismo para los nombres a y b.
-
>>>a=500
->>>b=500
->>>aisb
-False
+
>>>a=500
+>>>b=500
+>>>aisb
+False
Aquí a apunta a un 500 en memoria, y b apunta a otro 500 en memoria. Python sí creó dos objetos "500".
La pregunta es... ¿por qué la diferencia de comportamiento? Python (ojo, ver abajo) precachea (o tiene internalizado) algunos enteros chicos, porque sabe que siempre se van a usar.
diff --git a/preguntassinrespuesta/index.html b/preguntassinrespuesta/index.html
index 461e9f1fc..e7dcfd810 100644
--- a/preguntassinrespuesta/index.html
+++ b/preguntassinrespuesta/index.html
@@ -27,7 +27,7 @@
Frameworks web: django vs turbogears vs zope vs plone vs pylons
ORMS: comp">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/proyectos/index.html b/proyectos/index.html
index 899f9cdb6..7a522659b 100644
--- a/proyectos/index.html
+++ b/proyectos/index.html
@@ -28,7 +28,7 @@
Administrador de colas de mensajes, con soporte para múltiples protocolos: SMTP (mail), SMPP (S">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/pycamp2009resultados/index.html b/pycamp2009resultados/index.html
index be5981d8f..55d557f0a 100644
--- a/pycamp2009resultados/index.html
+++ b/pycamp2009resultados/index.html
@@ -28,7 +28,7 @@
La idea es que todos los que participaron agreguen a">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/pycamporm/index.html b/pycamporm/index.html
index 0ca6a3ba9..9d33a69aa 100644
--- a/pycamporm/index.html
+++ b/pycamporm/index.html
@@ -31,7 +31,7 @@
SqlAlchemy es un excelente orm cual nos permite trabajar con bases de datos relacionales sin tener que escribir sql, y pycamp.orm es una ">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
diff --git a/pyconar2015/index.html b/pyconar2015/index.html
index 0c1c9d1a8..66af5b14e 100644
--- a/pyconar2015/index.html
+++ b/pyconar2015/index.html
@@ -27,7 +27,7 @@
¿Por qué PyConAr en Mendoza?
Crear una comunidad de Python activa en Mendoza significa sumar más y más miembros interesados en esta tecnología, y para ello necesitamos encarar una estrategia ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/python3mil/index.html b/python3mil/index.html
index 6b44a23d9..df0c6c8e0 100644
--- a/python3mil/index.html
+++ b/python3mil/index.html
@@ -26,7 +26,7 @@
¿Python 3.0 no es compatible hacia atras con versiones pre">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/pythonzen/index.html b/pythonzen/index.html
index 16897e9d1..9f4406bfc 100644
--- a/pythonzen/index.html
+++ b/pythonzen/index.html
@@ -33,7 +33,7 @@
Plano es mejor que anidado.
Espaciado">
-
+
Ir al contenido principal
@@ -67,12 +67,12 @@
diff --git a/ramiromorales/index.html b/ramiromorales/index.html
index 3f6e40121..16802c4ff 100644
--- a/ramiromorales/index.html
+++ b/ramiromorales/index.html
@@ -29,7 +29,7 @@
Miembro de PyAr desde el 2006.
Obsesión actual (desde el 2006 bah">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-importtime
-importos
-not_executed=1
-while(not_executed):
-dt=list(time.localtime())
-hour=dt[3]
-minute=dt[4]
-sleep(1)
-ifhour==8andminute==30:# modificar hour y minute a la hora deseada
-os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
-not_executed=0
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+importtime
+importos
+not_executed=1
+while(not_executed):
+dt=list(time.localtime())
+hour=dt[3]
+minute=dt[4]
+sleep(1)
+ifhour==8andminute==30:# modificar hour y minute a la hora deseada
+os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
+not_executed=0
Comentarios
Facundo
Hay un par de cambios triviales para hacerle: se puede reemplazar el not_executed por un break, no hace falta declarar el encoding, y usar localtime() como corresponde..
-
#!/usr/bin/env python
-
-importtime
-importos
-while(True):
-dt=time.localtime()
-sleep(1)
-ifdt.tm_hour==8anddt.tm_min==30:# modificar hour y minute a la hora deseada
-os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
-break
+
#!/usr/bin/env python
+
+importtime
+importos
+while(True):
+dt=time.localtime()
+sleep(1)
+ifdt.tm_hour==8anddt.tm_min==30:# modificar hour y minute a la hora deseada
+os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
+break
... pero realmente está mal planteado la resolución: no hay que usar un while ahí:
-
importtime
-importos
-
-# modificar hour y minute a la hora deseada
-HOUR=8
-MIN=30
-
-t=time.localtime()
-nowhms=t.tm_hour*3600+t.tm_min*60+t.tm_sec
-alarm=HOUR*3600+MIN*60
-delta=alarm-nowhms
-ifdelta<0:
-# tomorrow
-delta+=3600*24
-time.sleep(delta)
-os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
+
importtime
+importos
+
+# modificar hour y minute a la hora deseada
+HOUR=8
+MIN=30
+
+t=time.localtime()
+nowhms=t.tm_hour*3600+t.tm_min*60+t.tm_sec
+alarm=HOUR*3600+MIN*60
+delta=alarm-nowhms
+ifdelta<0:
+# tomorrow
+delta+=3600*24
+time.sleep(delta)
+os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
DanielMoisset
Yo prefiero no sacar cuentas de fecha a mano, y en vez que datetime haga el trabajo sucio. Sobre todo porque maneja mejor casos delicados (que pasa si pongo la alarma justo antes de un cambio a horario de verano?) sin tener que pensarlos
-
importtime,datetime
-importos
-
-# modificar hour y minute a la hora deseada
-
-HOUR=8
-MIN=30
-
-now=datetime.datetime.now()
-alarm=now.replace(hour=HOUR,minute=MIN)
-ifalarm<now:
-# Set the alarm tomorrow
-alarm+=datetime.timedelta(days=1)
-time.sleep((alarm-now).seconds)
-os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
+
importtime,datetime
+importos
+
+# modificar hour y minute a la hora deseada
+
+HOUR=8
+MIN=30
+
+now=datetime.datetime.now()
+alarm=now.replace(hour=HOUR,minute=MIN)
+ifalarm<now:
+# Set the alarm tomorrow
+alarm+=datetime.timedelta(days=1)
+time.sleep((alarm-now).seconds)
+os.system("xdg-open /home/user/ring.ogg")# RingTone (?)
Juancarlospaco
Por lo menos en Linux se necesita el Shebang y declarar encoding, por que sino al usar "Vídeo-de-Música.ogv" de Ringtone traen problemas los acentos.
A esta altura creo que es más importante agregar el correcto coloreado de sintaxis y cuidar la ortografía, a discutir si poner o no el encoding y el shebang. La idea es que las recetas sean genéricas, con ese encoding y ese shebang, no cubris todos los casos. Pej, copias y pegas, y tu editor guarda en latin1??
Si funciona con:
-
usuario@maquina:~$pythonreceta.py
+
usuario@maquina:~$pythonreceta.py
Es más que suficiente. -- JoaquinSorianello 2010-11-08T10:56:40-0300
diff --git a/recetario/aletras/index.html b/recetario/aletras/index.html
index 75c22a93d..2bf297163 100644
--- a/recetario/aletras/index.html
+++ b/recetario/aletras/index.html
@@ -26,7 +26,7 @@
aLetras(numero) es una función a la que se le pasa un valor númerico y regresa un string con el valor numérico convertido a letras.
Los valores que pueden ser convertidos pertenecen al ran">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Los valores que pueden ser convertidos pertenecen al rango -999.999.999,99 : 999.999.999,99. Si se proporciona una cadena fuera de rango, retorna el string "0".
Siempre se trabaja con 2 decimales (se redondean los valores suministrados)
Ejemplos:
-
>>>aLetras(1234.56)
-' MIL DOSCIENTOS TREINTA Y CUATRO CON CINCUENTA Y SEIS CENTAVOS'
->>>aLetras(-240.99)
-'MENOS DOSCIENTOS CUARENTA CON NOVENTA Y NUEVE CENTAVOS'
->>>aLetras(100)
-'CIEN'
->>>aLetras(401201501.01)
-'CUATROCIENTOS UN MILLON DOSCIENTOS UN MIL QUINIENTOS UNO CON UN CENTAVOS'
->>>aLetras(-0.76)
-'MENOS CERO CON SETENTA Y SEIS CENTAVOS'
->>>aLetras(1000000000)
-'0'
+
>>>aLetras(1234.56)
+' MIL DOSCIENTOS TREINTA Y CUATRO CON CINCUENTA Y SEIS CENTAVOS'
+>>>aLetras(-240.99)
+'MENOS DOSCIENTOS CUARENTA CON NOVENTA Y NUEVE CENTAVOS'
+>>>aLetras(100)
+'CIEN'
+>>>aLetras(401201501.01)
+'CUATROCIENTOS UN MILLON DOSCIENTOS UN MIL QUINIENTOS UNO CON UN CENTAVOS'
+>>>aLetras(-0.76)
+'MENOS CERO CON SETENTA Y SEIS CENTAVOS'
+>>>aLetras(1000000000)
+'0'
Observaciones
La asignación y condicional en una línea -> numeros[1] = "UNO" if i == 2 else "UN" <- da problemas de sintaxis con versiones anteriores a Python 2.5.x
#fuente: Recetario de PyAR, http://python.com.ar/moin/Recetario
-#autor: Cesar E Portela
-#date: 06-05-2008
-#version: 2
-#para Python: 2.5.x
-
-defaLetras(numero):
-
-numeros={0:"CERO",2:"DOS",3:"TRES",4:"CUATRO",5:"CINCO",6:"SEIS",7:"SIETE",8:"OCHO",9:"NUEVE",
-10:"DIEZ",11:"ONCE",12:"DOCE",13:"TRECE",14:"CATORCE",15:"QUINCE",16:"DIECISEIS",17:"DIECISIETE",
-18:"DIECIOCHO",19:"DIECINUEVE",20:"VEINTE",30:"TREINTA",
-40:"CUARENTA",50:"CINCUENTA",60:"SESENTA",70:"SETENTA",80:"OCHENTA",90:"NOVENTA",100:"CIEN",
-500:"QUINIENTOS ",700:"SETECIENTOS ",900:"NOVECIENTOS "}
-
-ifabs(numero)>999999999.99:#mil millones, esta funcion procesa el rango [-999.999.999,99; 999.999.999,99]
-return("0",0)
-elifnumero<0:
-cadena="MENOS "
-else:
-cadena=""
-
-#separo el numero entregado entre parte entera y sus decimales (tomando solo 2 y redondeando para arriba)
-entero=int(abs(numero))
-decimales=int((round(abs(numero),2)+0.001)*100)%100
-
-#la parte entera es separada en grupos de tres digitos
-grupo1=int(entero/1000000)
-grupo2=int((int(entero)-int(grupo1)*1000000)/1000)
-grupo3=int(entero%1000)
-
-lista=[grupo1,grupo2,grupo3,decimales]
-
-if(grupo1+grupo2+grupo3)==0:
-cadena+=numeros[0]
-
-foriinxrange(4):
-unidad=lista[i]%10
-decena=lista[i]%100
-centena=(lista[i]/100)%10
-subcadena=""
-
-numeros[1]="UNO"ifi==2else"UN"
-
-ifi==0:#grupo 1: el de los millones
-ifdecena==1:
-subcadena=" MILLON "
-eliflista[i]>1:
-subcadena=" MILLONES "
-else:#aqui se entra si lista[i] == 0 y en ese caso, no hay nada que procesar
-continue#se sigue con la siguiente iteracion del bucle
-
-elifi==1:#grupo2: el de los miles
-iflista[i]==1:
-cadena+=" MIL "
-continue#se pasa a la siguiente iteracion
-eliflista[i]>1:
-subcadena=" MIL "
-else:#aqui se entra si lista[i] == 0 y en ese caso, no hay nada que procesar
-continue#se sigue con la siguiente iteracion del bucle
-
-elifi==3andlista[i]!=0:#grupo4: el de los centavos (decimales)
-cadena+=" CON "
-subcadena=" CENTAVOS"
-
-ifcentena!=0:
-ifcentena==1and(unidad+decena)==0:
-cadena+=numeros[100]
-continue
-elifcentena==1:
-cadena+="CIENTO "
-elifcentena==5:
-cadena+=numeros[500]
-elifcentena==7:
-cadena+=numeros[700]
-elifcentena==9:
-cadena+=numeros[900]
-else:
-cadena+=numeros[centena]+"CIENTOS "
-
-ifdecena!=0:
-ifdecena<21:
-cadena+=numeros[decena]
-elifdecena<30:
-cadena+="VENTI"+numeros[unidad]
-else:
-cadena+=numeros[(decena/10)*10]
-ifunidad>0:
-cadena+=" Y "+numeros[unidad]
-
-cadena+=subcadena
-
-returncadena
+
#fuente: Recetario de PyAR, http://python.com.ar/moin/Recetario
+#autor: Cesar E Portela
+#date: 06-05-2008
+#version: 2
+#para Python: 2.5.x
+
+defaLetras(numero):
+
+numeros={0:"CERO",2:"DOS",3:"TRES",4:"CUATRO",5:"CINCO",6:"SEIS",7:"SIETE",8:"OCHO",9:"NUEVE",
+10:"DIEZ",11:"ONCE",12:"DOCE",13:"TRECE",14:"CATORCE",15:"QUINCE",16:"DIECISEIS",17:"DIECISIETE",
+18:"DIECIOCHO",19:"DIECINUEVE",20:"VEINTE",30:"TREINTA",
+40:"CUARENTA",50:"CINCUENTA",60:"SESENTA",70:"SETENTA",80:"OCHENTA",90:"NOVENTA",100:"CIEN",
+500:"QUINIENTOS ",700:"SETECIENTOS ",900:"NOVECIENTOS "}
+
+ifabs(numero)>999999999.99:#mil millones, esta funcion procesa el rango [-999.999.999,99; 999.999.999,99]
+return("0",0)
+elifnumero<0:
+cadena="MENOS "
+else:
+cadena=""
+
+#separo el numero entregado entre parte entera y sus decimales (tomando solo 2 y redondeando para arriba)
+entero=int(abs(numero))
+decimales=int((round(abs(numero),2)+0.001)*100)%100
+
+#la parte entera es separada en grupos de tres digitos
+grupo1=int(entero/1000000)
+grupo2=int((int(entero)-int(grupo1)*1000000)/1000)
+grupo3=int(entero%1000)
+
+lista=[grupo1,grupo2,grupo3,decimales]
+
+if(grupo1+grupo2+grupo3)==0:
+cadena+=numeros[0]
+
+foriinxrange(4):
+unidad=lista[i]%10
+decena=lista[i]%100
+centena=(lista[i]/100)%10
+subcadena=""
+
+numeros[1]="UNO"ifi==2else"UN"
+
+ifi==0:#grupo 1: el de los millones
+ifdecena==1:
+subcadena=" MILLON "
+eliflista[i]>1:
+subcadena=" MILLONES "
+else:#aqui se entra si lista[i] == 0 y en ese caso, no hay nada que procesar
+continue#se sigue con la siguiente iteracion del bucle
+
+elifi==1:#grupo2: el de los miles
+iflista[i]==1:
+cadena+=" MIL "
+continue#se pasa a la siguiente iteracion
+eliflista[i]>1:
+subcadena=" MIL "
+else:#aqui se entra si lista[i] == 0 y en ese caso, no hay nada que procesar
+continue#se sigue con la siguiente iteracion del bucle
+
+elifi==3andlista[i]!=0:#grupo4: el de los centavos (decimales)
+cadena+=" CON "
+subcadena=" CENTAVOS"
+
+ifcentena!=0:
+ifcentena==1and(unidad+decena)==0:
+cadena+=numeros[100]
+continue
+elifcentena==1:
+cadena+="CIENTO "
+elifcentena==5:
+cadena+=numeros[500]
+elifcentena==7:
+cadena+=numeros[700]
+elifcentena==9:
+cadena+=numeros[900]
+else:
+cadena+=numeros[centena]+"CIENTOS "
+
+ifdecena!=0:
+ifdecena<21:
+cadena+=numeros[decena]
+elifdecena<30:
+cadena+="VENTI"+numeros[unidad]
+else:
+cadena+=numeros[(decena/10)*10]
+ifunidad>0:
+cadena+=" Y "+numeros[unidad]
+
+cadena+=subcadena
+
+returncadena
Autor / Autores:
CesarPortela
diff --git a/recetario/autocomplecionenconsolainteractiva/index.html b/recetario/autocomplecionenconsolainteractiva/index.html
index 1a647773a..348dd6213 100644
--- a/recetario/autocomplecionenconsolainteractiva/index.html
+++ b/recetario/autocomplecionenconsolainteractiva/index.html
@@ -29,7 +29,7 @@
import readline
excep'>
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
PYTHONSTARTUP=/home/tuusuario/.pythonrc#(aca importa que sea igual al nombre del alchivo).
+
PYTHONSTARTUP=/home/tuusuario/.pythonrc#(aca importa que sea igual al nombre del alchivo).
Lo que hace es darte Tab-completion en el interprete, cuando no se recuerda que métodos tiene mistring, en el intérprete se hace:
-
>>> mistring.<tab><tab>
+
>>> mistring.<tab><tab>
Lista los métodos y atributos disponibles.
Otros intérpretes ya lo hacen. ipython es notable por tener todo esto y mucho más, pero hay gente que no se acostumbra a usarlo todavia, y esto le pone Tab-completion al intérprete que es bastante común.
diff --git a/recetario/bloquearclickdelmouse/index.html b/recetario/bloquearclickdelmouse/index.html
index f57afcf01..5bc094ced 100644
--- a/recetario/bloquearclickdelmouse/index.html
+++ b/recetario/bloquearclickdelmouse/index.html
@@ -28,7 +28,7 @@
#!/usr/bin/env python
# -*- coding: utf-">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# License: GPLv3
-#import this
-try:
-fromTkinterimport*# Python2
-exceptImportError:
-fromtkinterimport*# Python3
-################################################################
-fromokbuttonimport*# This is the file, from the example ^_^
-################################################################
-root=Tk()
-root.title('Boton')
-root.focus()
-root.resizable(0,0)
-botoncito=OkButton(root,1,onImage=oexitOn,offImage=oexitOff,activeImage=oexitActive,bd=0,relief='flat',cursor='hand2',command=root.destroy)
-botoncito.pack()
-root.mainloop()
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# License: GPLv3
+#import this
+try:
+fromTkinterimport*# Python2
+exceptImportError:
+fromtkinterimport*# Python3
+################################################################
+fromokbuttonimport*# This is the file, from the example ^_^
+################################################################
+root=Tk()
+root.title('Boton')
+root.focus()
+root.resizable(0,0)
+botoncito=OkButton(root,1,onImage=oexitOn,offImage=oexitOff,activeImage=oexitActive,bd=0,relief='flat',cursor='hand2',command=root.destroy)
+botoncito.pack()
+root.mainloop()
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
diff --git a/recetario/bottle/galeria/index.html b/recetario/bottle/galeria/index.html
index e5fadca7b..e3a6289d2 100644
--- a/recetario/bottle/galeria/index.html
+++ b/recetario/bottle/galeria/index.html
@@ -27,7 +27,7 @@
Usa Bottle para servir 1 página incrustada en la propia aplicacion, la misma desplega HTML, CSS y Js.
#!/usr/bin/en">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Mejorando nuestro hola mundo en Bottle, ejemplo más completo, ideal para Plantilla para una App nueva.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-frombottleimportroute
-frombottleimportrun
-frombottleimportredirect
-frombottleimportdebug
-frombottleimporterror
-frombottleimportrequest
-frombottleimportabort
-importos
-#
-@route('/')
-defindex():
-return'Hola Mundo!'
-
-# Ejemplo de uso de bottle.request para mostrar tu direccion ip
-@route('/tuip')# ingresando a esa URL devuelve tu IP
-defshow_ip():
-ip=request.environ.get('REMOTE_ADDR')
-returnip
-
-# Ejemplo de uso de bottle.error para el 404, la pagina no existe
-@error(404)
-defmistake404(code):# Usando HTML directamente, de ejemplo.
-return'<title>bottle app</title><br><b>ERROR 404:la pagina no existe.</b>'
-
-# Ejemplo de uso de bottle.abort para URL no permitida, error 401
-@route('/restricted')
-defrestricted():
-abort(401,'ERROR 401:URL no permitida.')
-
-# Ejemplo de Redireccion bottle.redirect de URL, por URL incorrecta
-@route('/index.php')# si va a index.php
-defwrong():
-redirect("/")# enviarlo a "/"
-
-###############################################################################
-
-# Ejecucion de Main
-defmain():
-debug(True)# True para desarrollo, False para Produccion
-#
-# Por que es esto?: Puerto <1024 requiere Privilegios elevados
-ifos.geteuid()==0:# root check
-run(host='0.0.0.0',port=80,reloader=True)
-else:
-run(host='127.0.0.1',port=8080,reloader=True)
-
-if__name__=="__main__":
-main()
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+frombottleimportroute
+frombottleimportrun
+frombottleimportredirect
+frombottleimportdebug
+frombottleimporterror
+frombottleimportrequest
+frombottleimportabort
+importos
+#
+@route('/')
+defindex():
+return'Hola Mundo!'
+
+# Ejemplo de uso de bottle.request para mostrar tu direccion ip
+@route('/tuip')# ingresando a esa URL devuelve tu IP
+defshow_ip():
+ip=request.environ.get('REMOTE_ADDR')
+returnip
+
+# Ejemplo de uso de bottle.error para el 404, la pagina no existe
+@error(404)
+defmistake404(code):# Usando HTML directamente, de ejemplo.
+return'<title>bottle app</title><br><b>ERROR 404:la pagina no existe.</b>'
+
+# Ejemplo de uso de bottle.abort para URL no permitida, error 401
+@route('/restricted')
+defrestricted():
+abort(401,'ERROR 401:URL no permitida.')
+
+# Ejemplo de Redireccion bottle.redirect de URL, por URL incorrecta
+@route('/index.php')# si va a index.php
+defwrong():
+redirect("/")# enviarlo a "/"
+
+###############################################################################
+
+# Ejecucion de Main
+defmain():
+debug(True)# True para desarrollo, False para Produccion
+#
+# Por que es esto?: Puerto <1024 requiere Privilegios elevados
+ifos.geteuid()==0:# root check
+run(host='0.0.0.0',port=80,reloader=True)
+else:
+run(host='127.0.0.1',port=8080,reloader=True)
+
+if__name__=="__main__":
+main()
Nota: Hay más Features en Bottle_*, pero eso es suficiente para un Hola Mundo completo y didáctico.*
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
diff --git a/recetario/calculardigitoverificadormodulodiez/index.html b/recetario/calculardigitoverificadormodulodiez/index.html
index d9dde1d1a..c48949fac 100644
--- a/recetario/calculardigitoverificadormodulodiez/index.html
+++ b/recetario/calculardigitoverificadormodulodiez/index.html
@@ -26,7 +26,7 @@
digito_verificador_modulo10 es una función a la que se le pasa un código (ej. cadena '01234567890') y devuelve el dígito verificador a agregar correspondiente a la verificación módulo 10.
">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Esta verificación se usa en códigos de barra, por ej. en las facturas en el sistema impositivo argentino, donde se consigna el CUIT del emisor, CAI/CAE, número de factura, etc.
defdigito_verificador_modulo10(codigo):
-"Rutina para el cálculo del dígito verificador 'módulo 10'"
-# Ver RG 1702 AFIP
-# Etapa 1: comenzar desde la izquierda, sumar todos los caracteres ubicados en las posiciones impares.
-etapa1=sum([int(c)fori,cinenumerate(codigo)ifnoti%2])
-# Etapa 2: multiplicar la suma obtenida en la etapa 1 por el número 3
-etapa2=etapa1*3
-# Etapa 3: comenzar desde la izquierda, sumar todos los caracteres que están ubicados en las posiciones pares.
-etapa3=sum([int(c)fori,cinenumerate(codigo)ifi%2])
-# Etapa 4: sumar los resultados obtenidos en las etapas 2 y 3.
-etapa4=etapa2+etapa3
-# Etapa 5: buscar el menor número que sumado al resultado obtenido en la etapa 4 dé un número múltiplo de 10.
-# Este será el valor del dígito verificador del módulo 10.
-digito=10-(etapa4-(int(etapa4/10)*10))
-ifdigito==10:
-digito=0
-returnstr(digito)
+
defdigito_verificador_modulo10(codigo):
+"Rutina para el cálculo del dígito verificador 'módulo 10'"
+# Ver RG 1702 AFIP
+# Etapa 1: comenzar desde la izquierda, sumar todos los caracteres ubicados en las posiciones impares.
+etapa1=sum([int(c)fori,cinenumerate(codigo)ifnoti%2])
+# Etapa 2: multiplicar la suma obtenida en la etapa 1 por el número 3
+etapa2=etapa1*3
+# Etapa 3: comenzar desde la izquierda, sumar todos los caracteres que están ubicados en las posiciones pares.
+etapa3=sum([int(c)fori,cinenumerate(codigo)ifi%2])
+# Etapa 4: sumar los resultados obtenidos en las etapas 2 y 3.
+etapa4=etapa2+etapa3
+# Etapa 5: buscar el menor número que sumado al resultado obtenido en la etapa 4 dé un número múltiplo de 10.
+# Este será el valor del dígito verificador del módulo 10.
+digito=10-(etapa4-(int(etapa4/10)*10))
+ifdigito==10:
+digito=0
+returnstr(digito)
Chequea la versión de la Distribución Linux, y actúa en función de eso. Utiliza el módulo platform
-
importplatform
-
-osInfo=('Ubuntu','10.10','maverick')
-sysInfo=platform.linux_distribution()
-
-ifosInfo==sysInfo:
-print(" OK ")
-# Aca va que hacer si esta OK
-else:
-print(" ERROR ")
-# Aca va que hacer si la version no es correcta
+
importplatform
+
+osInfo=('Ubuntu','10.10','maverick')
+sysInfo=platform.linux_distribution()
+
+ifosInfo==sysInfo:
+print(" OK ")
+# Aca va que hacer si esta OK
+else:
+print(" ERROR ")
+# Aca va que hacer si la version no es correcta
diff --git a/recetario/chequearinterfacesinternetlinux/index.html b/recetario/chequearinterfacesinternetlinux/index.html
index 7ae2e5b90..2e36e0763 100644
--- a/recetario/chequearinterfacesinternetlinux/index.html
+++ b/recetario/chequearinterfacesinternetlinux/index.html
@@ -31,7 +31,7 @@
'''
Lis">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
Si te esta pasando que necesitas saber ¿en qué placa de red tenés internet en Gnu/Linux con Python ? Bueno, por ahí esto te sirve 🙂
-
importsocket
-
-DEBUG=True
-
-deflist_net_devices():
-'''
- Lista todas las placas de red.
- Retorna:
- Lista con diccionarios, cada diccionario de la lista tiene
- como key el nombre de la iface asignada y los valores del
- diccionario son los datos correspondiente a la interfaz de red
- '''
-fh=open('/proc/net/dev','r')
-lines=fh.readlines()
-fh.close()
-
-ifaces=[]
-forlineinlines:
-if':'inline:
-iface_name,iface_data=line.split(':')
-new_iface={}
-# limpiamos iface_data ...
-data=[]
-foriteminiface_data.strip().split(' '):
-ifitem!='':
-data.append(item)
-new_iface[iface_name.strip()]=data
-ifaces.append(new_iface)
-
-returnifaces
-
-definfo_net_device(device):
-'''
- Devuelve informacion de un dispositivo de red en particular
- Argumentos:
- device(str)
- Retorna:
- Diccionario siendo la clave el device solicitado y
- los datos como values.
- None en caso de no encontrarse el dispositivo de red.
- Funciones:
- list_net_devices
- '''
-ifnotisinstance(device,str):
-raiseException,'el device debe ser un string, obtuve %s'%repr(device)
-
-devices=list_net_devices()
-info_iface={}
-forifaceindevices:
-kw=iface.keys().pop()
-ifkw==device:
-info_iface[kw]=iface[kw]
-returninfo_iface
-returnNone
-
-defroute_net_devices():
-'''
- Devuelve las rutas asignadas a los dispositivos de red
- Retorna:
- Diccionario siendo la clave el dispositivo de red y su
- value la ip de la ruta por defecto como string.
- '''
-fh=open('/proc/net/route','r')
-lines=fh.readlines()
-fh.close()
-devices={}
-
-forlineinlines:
-ifline.split('\t')[0]!='Iface':
-iface=line.split('\t')[0]
-hexgw=line.split('\t')[2]
-gw='%s.%s.%s.%s'%(int(hexgw[6:8],16),
-int(hexgw[4:6],16),
-int(hexgw[2:4],16),
-int(hexgw[:2],16),
-)
-devices[iface]=gw
-returndevices
-
-defip_port_open(ip,port):
-'''
- Chequea si un puerto en una ip dada se encuentra abierto o no.
- Argumentos:
- ip(str)
- port(int)
- Retorna:
- True(bool), si el puerto en la ip dada esta abierto
- False(bool), si el puerto en la ip dada no esta abierto
- '''
-ifnotisinstance(ip,str):
-raiseException,'la ip debe ser un string, obtuve %s'%repr(ip)
-ifnotisinstance(port,int):
-raiseException,'el puerto debe ser un int, obtuve %s'%repr(port)
-
-s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
-try:
-s.connect((ip,int(port)))
-s.shutdown(2)
-returnTrue
-except:
-returnFalse
-
-defhost_port_open(hostname,port):
-'''
- Chequea si un puerto en un host dado se encuentra abierto o no.
- Argumentos:
- hostname(str)
- port(int)
- Retorna:
- True(bool), si el puerto en el hostname dado esta abierto
- False(bool), si el puerto en el hostname dado no esta abierto
- Funciones:
- ip_port_open
- '''
-ifnotisinstance(hostname,str):
-raiseException,'el hostname debe ser un string, obtuve %s'%repr(hostname)
-ifnotisinstance(port,int):
-raiseException,'el puerto debe ser un int, obtuve %s'%repr(port)
-
-ip=socket.gethostbyname(hostname)
-returnip_port_open(ip,port)
-
-defdns_working(domain):
-'''
- Chequea si podemos resolver un dominio, por lo tanto, si funcionan los DNS
- Argumentos:
- domain(str)
- Retorna:
- True(bool) en caso de poder resolver el dominio
- False(bool) en caso de no poder resolver el dominio
- '''
-ifnotisinstance(domain,str):
-raiseException,'el domain debe ser un string'
-
-try:
-socket.gethostbyname(domain)
-returnTrue
-exceptException:
-returnFalse
-
-defgateway_recheable(dest_addr=None,inet=None):
-'''
- Chequea si tenemos conexion contra el gateway pasado como parametro.
- Si el gateway bloquea los paquetes icmp, este metodo no funciona.
- Argumentos:
- gateway(str)
- Retorna:
- True(bool) si el gateway es recheable
- False(bool) si el gateways no es recheable
- '''
-
-ifnotisinstance(dest_addr,str):
-raiseException,'gateway debe ser una ip como string'
-
-defcreate_sockets(ttl):
-"""
- Sockets necesarios para el traceroute, enviamos por udp y
- recibimos por icmp. Al usar icmp, precisamos permisos de super
- administrador.
- Argumentos:
- ttl(int) TimeToLive, campo que se setea en el paquete
- y cual se decrementa en 1 a medida que pasa por cada
- host / router
- Retorna:
- recv_socket, socket icmp en el que se escuchan datos
- send_socket, socket udp por el cual se envian datos
- Funciones:
- dns_working
- """
-icmp=socket.getprotobyname('icmp')
-udp=socket.getprotobyname('udp')
-timeout=2
-
-recv_socket=socket.socket(socket.AF_INET,socket.SOCK_RAW,icmp)
-recv_socket.settimeout(timeout)
-send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,udp)
-send_socket.setsockopt(socket.SOL_IP,socket.IP_TTL,ttl)
-returnrecv_socket,send_socket
-
-ttl=1
-port=33434
-recheable=False
-remote_host='google.com'# host usado para comprobar internet
-
-try:
-ifdest_addrisnotNone:
-recv_socket,send_socket=create_sockets(ttl)
-recv_socket.bind(("",port))
-send_socket.sendto("",(dest_addr,port))
-_,curr_addr=recv_socket.recvfrom(512)
-curr_addr=curr_addr[0]
-send_socket.close()
-recv_socket.close()
-ifcurr_addr==dest_addr:
-recheable=True
-
-ifinetisTrue:
-max_hops=30
-max_hops_failures=20
-failures=0
-accerted_hops=0
-
-ifnotdns_working(remote_host):
-returnFalse
-dest_addr=socket.gethostbyname(remote_host)
-
-whileTrue:
-recv_socket,send_socket=create_sockets(ttl)
-recv_socket.bind(("",port))
-send_socket.sendto("",(remote_host,port))
-try:
-_,curr_addr=recv_socket.recvfrom(512)
-curr_addr=curr_addr[0]
-ifcurr_addrisnotNone:
-accerted_hops+=1
-ifcurr_addr==dest_addr:
-recheable=True
-send_socket.close()
-recv_socket.close()
-break
-else:
-failures+=1
-
-exceptException,ex:
-failures+=1
-
-ifDEBUG:
-print'ttl: %s chost: %s rhost: %s failures: %s accerts: %s'%(ttl,
-curr_addr,
-dest_addr,
-failures,
-accerted_hops)
-
-ttl+=1
-send_socket.close()
-recv_socket.close()
-
-iffailures>=max_hops_failures:
-recheable=False
-break
-
-exceptException,ex:
-recheable=False
-
-returnrecheable
+
importsocket
+
+DEBUG=True
+
+deflist_net_devices():
+'''
+ Lista todas las placas de red.
+ Retorna:
+ Lista con diccionarios, cada diccionario de la lista tiene
+ como key el nombre de la iface asignada y los valores del
+ diccionario son los datos correspondiente a la interfaz de red
+ '''
+fh=open('/proc/net/dev','r')
+lines=fh.readlines()
+fh.close()
+
+ifaces=[]
+forlineinlines:
+if':'inline:
+iface_name,iface_data=line.split(':')
+new_iface={}
+# limpiamos iface_data ...
+data=[]
+foriteminiface_data.strip().split(' '):
+ifitem!='':
+data.append(item)
+new_iface[iface_name.strip()]=data
+ifaces.append(new_iface)
+
+returnifaces
+
+definfo_net_device(device):
+'''
+ Devuelve informacion de un dispositivo de red en particular
+ Argumentos:
+ device(str)
+ Retorna:
+ Diccionario siendo la clave el device solicitado y
+ los datos como values.
+ None en caso de no encontrarse el dispositivo de red.
+ Funciones:
+ list_net_devices
+ '''
+ifnotisinstance(device,str):
+raiseException,'el device debe ser un string, obtuve %s'%repr(device)
+
+devices=list_net_devices()
+info_iface={}
+forifaceindevices:
+kw=iface.keys().pop()
+ifkw==device:
+info_iface[kw]=iface[kw]
+returninfo_iface
+returnNone
+
+defroute_net_devices():
+'''
+ Devuelve las rutas asignadas a los dispositivos de red
+ Retorna:
+ Diccionario siendo la clave el dispositivo de red y su
+ value la ip de la ruta por defecto como string.
+ '''
+fh=open('/proc/net/route','r')
+lines=fh.readlines()
+fh.close()
+devices={}
+
+forlineinlines:
+ifline.split('\t')[0]!='Iface':
+iface=line.split('\t')[0]
+hexgw=line.split('\t')[2]
+gw='%s.%s.%s.%s'%(int(hexgw[6:8],16),
+int(hexgw[4:6],16),
+int(hexgw[2:4],16),
+int(hexgw[:2],16),
+)
+devices[iface]=gw
+returndevices
+
+defip_port_open(ip,port):
+'''
+ Chequea si un puerto en una ip dada se encuentra abierto o no.
+ Argumentos:
+ ip(str)
+ port(int)
+ Retorna:
+ True(bool), si el puerto en la ip dada esta abierto
+ False(bool), si el puerto en la ip dada no esta abierto
+ '''
+ifnotisinstance(ip,str):
+raiseException,'la ip debe ser un string, obtuve %s'%repr(ip)
+ifnotisinstance(port,int):
+raiseException,'el puerto debe ser un int, obtuve %s'%repr(port)
+
+s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+try:
+s.connect((ip,int(port)))
+s.shutdown(2)
+returnTrue
+except:
+returnFalse
+
+defhost_port_open(hostname,port):
+'''
+ Chequea si un puerto en un host dado se encuentra abierto o no.
+ Argumentos:
+ hostname(str)
+ port(int)
+ Retorna:
+ True(bool), si el puerto en el hostname dado esta abierto
+ False(bool), si el puerto en el hostname dado no esta abierto
+ Funciones:
+ ip_port_open
+ '''
+ifnotisinstance(hostname,str):
+raiseException,'el hostname debe ser un string, obtuve %s'%repr(hostname)
+ifnotisinstance(port,int):
+raiseException,'el puerto debe ser un int, obtuve %s'%repr(port)
+
+ip=socket.gethostbyname(hostname)
+returnip_port_open(ip,port)
+
+defdns_working(domain):
+'''
+ Chequea si podemos resolver un dominio, por lo tanto, si funcionan los DNS
+ Argumentos:
+ domain(str)
+ Retorna:
+ True(bool) en caso de poder resolver el dominio
+ False(bool) en caso de no poder resolver el dominio
+ '''
+ifnotisinstance(domain,str):
+raiseException,'el domain debe ser un string'
+
+try:
+socket.gethostbyname(domain)
+returnTrue
+exceptException:
+returnFalse
+
+defgateway_recheable(dest_addr=None,inet=None):
+'''
+ Chequea si tenemos conexion contra el gateway pasado como parametro.
+ Si el gateway bloquea los paquetes icmp, este metodo no funciona.
+ Argumentos:
+ gateway(str)
+ Retorna:
+ True(bool) si el gateway es recheable
+ False(bool) si el gateways no es recheable
+ '''
+
+ifnotisinstance(dest_addr,str):
+raiseException,'gateway debe ser una ip como string'
+
+defcreate_sockets(ttl):
+"""
+ Sockets necesarios para el traceroute, enviamos por udp y
+ recibimos por icmp. Al usar icmp, precisamos permisos de super
+ administrador.
+ Argumentos:
+ ttl(int) TimeToLive, campo que se setea en el paquete
+ y cual se decrementa en 1 a medida que pasa por cada
+ host / router
+ Retorna:
+ recv_socket, socket icmp en el que se escuchan datos
+ send_socket, socket udp por el cual se envian datos
+ Funciones:
+ dns_working
+ """
+icmp=socket.getprotobyname('icmp')
+udp=socket.getprotobyname('udp')
+timeout=2
+
+recv_socket=socket.socket(socket.AF_INET,socket.SOCK_RAW,icmp)
+recv_socket.settimeout(timeout)
+send_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,udp)
+send_socket.setsockopt(socket.SOL_IP,socket.IP_TTL,ttl)
+returnrecv_socket,send_socket
+
+ttl=1
+port=33434
+recheable=False
+remote_host='google.com'# host usado para comprobar internet
+
+try:
+ifdest_addrisnotNone:
+recv_socket,send_socket=create_sockets(ttl)
+recv_socket.bind(("",port))
+send_socket.sendto("",(dest_addr,port))
+_,curr_addr=recv_socket.recvfrom(512)
+curr_addr=curr_addr[0]
+send_socket.close()
+recv_socket.close()
+ifcurr_addr==dest_addr:
+recheable=True
+
+ifinetisTrue:
+max_hops=30
+max_hops_failures=20
+failures=0
+accerted_hops=0
+
+ifnotdns_working(remote_host):
+returnFalse
+dest_addr=socket.gethostbyname(remote_host)
+
+whileTrue:
+recv_socket,send_socket=create_sockets(ttl)
+recv_socket.bind(("",port))
+send_socket.sendto("",(remote_host,port))
+try:
+_,curr_addr=recv_socket.recvfrom(512)
+curr_addr=curr_addr[0]
+ifcurr_addrisnotNone:
+accerted_hops+=1
+ifcurr_addr==dest_addr:
+recheable=True
+send_socket.close()
+recv_socket.close()
+break
+else:
+failures+=1
+
+exceptException,ex:
+failures+=1
+
+ifDEBUG:
+print'ttl: %s chost: %s rhost: %s failures: %s accerts: %s'%(ttl,
+curr_addr,
+dest_addr,
+failures,
+accerted_hops)
+
+ttl+=1
+send_socket.close()
+recv_socket.close()
+
+iffailures>=max_hops_failures:
+recheable=False
+break
+
+exceptException,ex:
+recheable=False
+
+returnrecheable
Ejemplitos de cómo se usa:
-
In[8]:# chequeamos conexion contra la db
-
-In[9]:host_port_open('gondor.airtrack.ovz',3306)
-Out[9]:True
-
-In[10]:# http de googl ...
-
-In[11]:host_port_open('www.google.com',80)
-Out[11]:True
-
-In[12]:host_port_open('www.google.com',81)
-Out[12]:False
-
-In[15]:# pedimos el gateway de la eth1 ...
-
-In[16]:route_net_devices()
-Out[16]:{'eth1':'192.168.1.1','eth2':'0.0.0.0','lo':'0.0.0.0'}
-
-In[17]:# aha ... ahora veamos si tenemos conexion contra ese gw ...
-
-In[18]:gateway_recheable(route_net_devices()['eth1'])
-Out[18]:True
-
-In[19]:# y nos da internet ese gw ? ...
-
-In[20]:gateway_recheable(route_net_devices()['eth1'],inet=True)
-ttl:1chost:192.168.1.1rhost:209.85.195.104failures:0accerts:1
-ttl:2chost:192.168.1.1rhost:209.85.195.104failures:1accerts:1
-ttl:3chost:192.168.1.1rhost:209.85.195.104failures:2accerts:1
-ttl:4chost:192.168.1.1rhost:209.85.195.104failures:3accerts:1
-ttl:5chost:192.168.1.1rhost:209.85.195.104failures:4accerts:1
-ttl:6chost:200.89.165.213rhost:209.85.195.104failures:4accerts:2
-ttl:7chost:200.89.165.194rhost:209.85.195.104failures:4accerts:3
-ttl:8chost:200.89.165.194rhost:209.85.195.104failures:5accerts:3
-ttl:9chost:200.89.165.194rhost:209.85.195.104failures:6accerts:3
-ttl:10chost:200.49.159.254rhost:209.85.195.104failures:6accerts:4
-ttl:11chost:209.85.251.28rhost:209.85.195.104failures:6accerts:5
-ttl:12chost:209.85.251.6rhost:209.85.195.104failures:6accerts:6
-Out[20]:True
+
In[8]:# chequeamos conexion contra la db
+
+In[9]:host_port_open('gondor.airtrack.ovz',3306)
+Out[9]:True
+
+In[10]:# http de googl ...
+
+In[11]:host_port_open('www.google.com',80)
+Out[11]:True
+
+In[12]:host_port_open('www.google.com',81)
+Out[12]:False
+
+In[15]:# pedimos el gateway de la eth1 ...
+
+In[16]:route_net_devices()
+Out[16]:{'eth1':'192.168.1.1','eth2':'0.0.0.0','lo':'0.0.0.0'}
+
+In[17]:# aha ... ahora veamos si tenemos conexion contra ese gw ...
+
+In[18]:gateway_recheable(route_net_devices()['eth1'])
+Out[18]:True
+
+In[19]:# y nos da internet ese gw ? ...
+
+In[20]:gateway_recheable(route_net_devices()['eth1'],inet=True)
+ttl:1chost:192.168.1.1rhost:209.85.195.104failures:0accerts:1
+ttl:2chost:192.168.1.1rhost:209.85.195.104failures:1accerts:1
+ttl:3chost:192.168.1.1rhost:209.85.195.104failures:2accerts:1
+ttl:4chost:192.168.1.1rhost:209.85.195.104failures:3accerts:1
+ttl:5chost:192.168.1.1rhost:209.85.195.104failures:4accerts:1
+ttl:6chost:200.89.165.213rhost:209.85.195.104failures:4accerts:2
+ttl:7chost:200.89.165.194rhost:209.85.195.104failures:4accerts:3
+ttl:8chost:200.89.165.194rhost:209.85.195.104failures:5accerts:3
+ttl:9chost:200.89.165.194rhost:209.85.195.104failures:6accerts:3
+ttl:10chost:200.49.159.254rhost:209.85.195.104failures:6accerts:4
+ttl:11chost:209.85.251.28rhost:209.85.195.104failures:6accerts:5
+ttl:12chost:209.85.251.6rhost:209.85.195.104failures:6accerts:6
+Out[20]:True
diff --git a/recetario/chequeo_de_paquetes_apt_linux/index.html b/recetario/chequeo_de_paquetes_apt_linux/index.html
index 77b5b95c7..41343d8b5 100644
--- a/recetario/chequeo_de_paquetes_apt_linux/index.html
+++ b/recetario/chequeo_de_paquetes_apt_linux/index.html
@@ -31,7 +31,7 @@
#
cache = apt.C">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
Cómo saber si un paquete está instalado, o no, y si el mismo existe usando Python. Se muestra un ejemplo interactivo simple.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-importapt
-#
-cache=apt.Cache()
-cache.open()
-program=raw_input(' Cual es el nombre del programa?: ')
-ifprogramincache:
-ifcache[program].is_installed:
-print(' El programa esta instalado!\n')
-else:
-print(' El programa no esta instalado!\n')
-else:
-print(' Estas seguro del Nombre del programa?, el programa no existe!\n')
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+importapt
+#
+cache=apt.Cache()
+cache.open()
+program=raw_input(' Cual es el nombre del programa?: ')
+ifprogramincache:
+ifcache[program].is_installed:
+print(' El programa esta instalado!\n')
+else:
+print(' El programa no esta instalado!\n')
+else:
+print(' Estas seguro del Nombre del programa?, el programa no existe!\n')
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
Fe de Erratas: seguramente hay una forma mejor de hacerlo, pero esta funciona correctamente.
diff --git a/recetario/comobajartodoslosbuffersaldisco/index.html b/recetario/comobajartodoslosbuffersaldisco/index.html
index 62d35cac5..1ca38f558 100644
--- a/recetario/comobajartodoslosbuffersaldisco/index.html
+++ b/recetario/comobajartodoslosbuffersaldisco/index.html
@@ -28,7 +28,7 @@
Cerrar correctamente tu programa
Mejores Prácticas (o Best Practice) de cómo debería cerrarse tu programa de una manera linux-friendly, para p">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
Mejores Prácticas (o Best Practice) de cómo debería cerrarse tu programa de una manera linux-friendly, para prevenir corrupción/pérdida de datos.
Disclaimer: Esto es más relacionado al OS que a Python en si, válido para los SO tipo Unix, pero es importante para lograr una aplicacion que funcione como debe.
-
importos
-
-# Tu programa debe invocar este comando y luego cerrarse.
-os.system('sync')
-
-**¿Porqué?:**EnLinuxlosdatosqueteóricamentedeberíanestarescritoseneldisco,nosiempreloestanenlarealidad,porunperíododetiempovariabledeunossegundospodríanmantenerseenRAM.EltiempoensegundosvaríasegúnlasconfiguracionesdelKernel.
+
importos
+
+# Tu programa debe invocar este comando y luego cerrarse.
+os.system('sync')
+
+**¿Porqué?:**EnLinuxlosdatosqueteóricamentedeberíanestarescritoseneldisco,nosiempreloestanenlarealidad,porunperíododetiempovariabledeunossegundospodríanmantenerseenRAM.EltiempoensegundosvaríasegúnlasconfiguracionesdelKernel.
Ejemplo:
-
cat/proc/sys/vm/dirty_writeback_centisecs
-500
+
cat/proc/sys/vm/dirty_writeback_centisecs
+500
Esto significa que ningun dato se escribirá a disco realmente durante 5 Segundos, esto parece poco, pero en algunos casos como Notebooks o equipos con UPS este valor puede estar en 1500, es decir 15 segundos (lo que es un montón en Infomática). No piensen que este valor se puede reducir, esto tendría al Kernel contantemente escribiendo la RAM al disco. Esto es más notable en EXT4 con Extents activados. Alternativamente al ejemplo puedes agregar que detecte que OS es y ejecutar o no sync, también puede solucionar algunos "Segmentation Fault" misteriosos al cerrar tu programa.
En mi Notebook, obtengo este resultado:
(Si escribo un programa que no invoca a sync puedo perder 10 segundos de datos).
Este ejemplo muestra cómo levantar un servidor web en Python sirviendo el contenido del directorio actual utilizando threads para manejar las solicitudes.
Para usarlo, simplemente hay que llamar a este módulo desde la línea de comando, si se llamara test.py entonces correr "python test.py"
Inicializá tu proyecto. Por ejemplo el proyecto zaraza
-
$mkproject-tpackagezaraza
+
$mkproject-tpackagezaraza
Se te solicitarán algunos datos (nombre del proyecto, autor, licencia, etc.) y ¡(casi) listo! Estarás trabajando en tu proyecto zaraza. Tu prompt se verá así:
-
(zaraza)tin@morocha:~/proyectos/zaraza$
+
(zaraza)tin@morocha:~/proyectos/zaraza$
¿Qué sucedió? Se creó un directorio ~/proyectos/zaraza para tu proyecto, asociado a un virtualenv ubicado en ~/.virtualenvs /zaraza. skeleton automáticamente creó una estructura básica de paquete python ~/proyectos/zaraza/src incluyendo un setup.py basado en distribute.
Instalá tu paquete en el virtualenv, para poder importarlo desde cualquier lado
Esto agrega el directorio de desarrollo de tu proyecto al PYTHONPATH del virtualenv, de modo que puedes importar zaraza desde cualquier lado dentro del virtualenv (por ejemplo, cuando hagas una carpeta src/test al nivel de '/src/zaraza'
¿Y ahora?
Cada vez que quieras trabajar en tu proyecto zaraza podes correr
-
$workonzaraza
+
$workonzaraza
Para salir del virtualenv
-
(zaraza)$deactivate
+
(zaraza)$deactivate
Algunos tips más a modo de despedida
Virtualenwrapper es totalmente hookeable y extensible. Esta receta propone usar skeleton (que funciona como plugin de virtualenvwrapper.project) para crear una estructura de paquete estándar básica, pero hay plugins para proyectos más específicos. Por ejemplo virtualenwrapper.django
diff --git a/recetario/crearejecutablewindows/index.html b/recetario/crearejecutablewindows/index.html
index 577f5831b..988ded825 100644
--- a/recetario/crearejecutablewindows/index.html
+++ b/recetario/crearejecutablewindows/index.html
@@ -28,7 +28,7 @@
Crear un ejecutable (.EXE) nativo para Windows (que no requiera tener Python instalado)
Generar un archivo autoextraible similar a un instalador (pero más ">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
Luego en la carpeta de la aplicación, por línea de comandos, ejecutamos este script:
-
python setup.py py2exe
+
python setup.py py2exe
Con lo que se generará una carpeta dist con los siguientes archivos:
@@ -131,7 +131,7 @@
Empaquetando Programas De Python Para Windows
Creando un instalador simple con 7-Zip
Con 7-zip se puede crear un único archivo comprimido autoextraible (ejecutable), con una muy buena tasa de compresión y de manera muy simple.
Para ello, ejecutar 7-Zip en la linea de comandos sobre la carpeta de la aplicación:
-
7z.exe a -sfx setup.exe dist
+
7z.exe a -sfx setup.exe dist
Con esto nos creará un archivo setup.exe que al ejecutarlo descomprimirá automáticamente la carpeta de nuestra aplicación. Este archivo contiene todo lo necesario para ejecutar la aplicación.
Este ejemplo usa la línea de comando, pero también se puede usar la interfase visual integrada al explorador de windows de 7-Zip (click derecho sobre la carpeta dist, en el menú contextual elejir 7-zip, añadir al archivo, y tildar opción "Crear archivo SFX")
diff --git a/recetario/crearejecutablewindowsdesdelinux/index.html b/recetario/crearejecutablewindowsdesdelinux/index.html
index 4700f75f8..ab93a2bd4 100644
--- a/recetario/crearejecutablewindowsdesdelinux/index.html
+++ b/recetario/crearejecutablewindowsdesdelinux/index.html
@@ -35,7 +35,7 @@
Una distribución de Linux http://distrowatch.com/.
Un Wine instal">
-
+
Ir al contenido principal
@@ -69,12 +69,12 @@
Para instalar el MSI de Python para Windows se usa:
-
$winemsiexec/ipython-2.5.1.msi
+
$winemsiexec/ipython-2.5.1.msi
Luego instale las dependencias de su programa.
Por ejemplo, para instalar pygame:
-
$winepygame-1.7.1release.win32-py2.5.exe
+
$winepygame-1.7.1release.win32-py2.5.exe
O doble clic sobre el icono del programa.
Es importante decirle que python haga los .pyc, cuando sea preguntado por el instalador.
@@ -123,54 +123,54 @@
Empaquetando Programas De Python Para Windows Desde Linux
Aún habiendo hecho lo anterior, puede pasar que cuando se intenta "compilar",aparezca un mensaje que
advierte que no se encontró un archivo .pyc, debe buscarse el .py correspondiente. Y ejecutarlo con
(Repita la operación con cada modulo en el que aparezca el error)
Es importante hacer notar que aunque alguna característica del programa puede NO funcionar en Wine, como por ejemplo pygame, igualmente puede "compilarse" (empaquetarse) correctamente.
Pyinstaller
Pyinstaller no se instala, como py2exe. Sin que se descomprime en un directorio. Se necesita un directorio por cada versión de Python que uno quiera usar con Pyinstaller.
Para configurar Pyinstaller siga las instrucciones del manual.
Lo que no es claro en el manual es como crear los ejecutables. La explicación es complicada y retorcida, sin embargo es muy sencillo. Ejecute algo como:
Esto crea un archivo principal.spec en el directorio c:\miproyecto\Pyinstallerdist
El archivo .spec se hace solo una vez, en general no es necesario cambiarlo.
Para automatizar la compilación primero borramos lo que este hecho de antes, esto hace más lento el empaquetamiento, pero evitamos el riesgo de que se empaqueten cosas viejas con las nuevas. Especialmente si las modificaciones hechas son muy pequeñas.
Inno Setup Compiler crea instaladores para Windows, funciona perfectamente bajo Linux con Wine. Es una aplicación sumamente fácil de usar, y tiene un asistente muy bueno. Por lo que no tiene sentido comentarla, sin embargo hay un truco que merece la pena.
Para automatizar la creación del instalador de nuestra aplicación podemos ejecutar:
Como se darán cuenta, todas estas instrucciones de linea de comando se pueden colocar en un archivo de Bash, y hacer que todo el proceso de empaquetado quede totalmente automatizado.
Nota: El mensaje a cifrar parece que tiene que tener un largo de 8 (no sé mucho de blowfish :D)
diff --git a/recetario/dbfpy/index.html b/recetario/dbfpy/index.html
index 133be7531..0eebeecbb 100644
--- a/recetario/dbfpy/index.html
+++ b/recetario/dbfpy/index.html
@@ -26,7 +26,7 @@
Esta receta es un ejemplo de cómo acceder nativamente desde Python a bases de datos en formato DBF (dBase, Foxpro, Clipper, etc.), sin necesidad de ODBC u otras herramientas.
Utiliza DbfPy">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/recetario/decodehtmlentities/index.html b/recetario/decodehtmlentities/index.html
index c1709acdb..b6a2a86f1 100644
--- a/recetario/decodehtmlentities/index.html
+++ b/recetario/decodehtmlentities/index.html
@@ -31,7 +31,7 @@
@param text The HTML (or XML) source t'>
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
importre
-importhtmlentitydefs
-
-defunescape(text,encoding="UTF-8"):
-"""
- Removes HTML or XML character references and entities from a text string.
-
- @param text The HTML (or XML) source text.
- @return The unescaped text as a Unicode.
- """
-
-deffixup(m):
-text=m.group(0)
-iftext[:2]=="&#":
-# character reference
-try:
-iftext[:3]=="&#x":
-text=unichr(int(text[3:-1],16))
-else:
-text=unichr(int(text[2:-1]))
-exceptValueError:
-pass
-else:
-# named entity
-try:
-text=unichr(htmlentitydefs.name2codepoint[text[1:-1]])
-exceptKeyError:
-pass
-
-returntext
-
-# Decode string as needed
-text=text.decode(encoding)ifisinstance(text,str)elsetext
-returntextandre.sub("&#?\w+;",fixup,text)
+
importre
+importhtmlentitydefs
+
+defunescape(text,encoding="UTF-8"):
+"""
+ Removes HTML or XML character references and entities from a text string.
+
+ @param text The HTML (or XML) source text.
+ @return The unescaped text as a Unicode.
+ """
+
+deffixup(m):
+text=m.group(0)
+iftext[:2]=="&#":
+# character reference
+try:
+iftext[:3]=="&#x":
+text=unichr(int(text[3:-1],16))
+else:
+text=unichr(int(text[2:-1]))
+exceptValueError:
+pass
+else:
+# named entity
+try:
+text=unichr(htmlentitydefs.name2codepoint[text[1:-1]])
+exceptKeyError:
+pass
+
+returntext
+
+# Decode string as needed
+text=text.decode(encoding)ifisinstance(text,str)elsetext
+returntextandre.sub("&#?\w+;",fixup,text)
Gracias Martin Conte Mac Donell! 😉
diff --git a/recetario/displaylcd7segmentos/index.html b/recetario/displaylcd7segmentos/index.html
index 19e09f15c..6783f9788 100644
--- a/recetario/displaylcd7segmentos/index.html
+++ b/recetario/displaylcd7segmentos/index.html
@@ -26,7 +26,7 @@
Toma los sys.argv, tiene punto, tiene guion de negativo, tiene import con wilcard (ups!).
Útil para importarlo dentro de otro program">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Si usamos herencia normal de modelos (no abstracta), se vuelve difícil obtener el objeto original de la base de datos cuando sólo tenemos una referencia a un ancestro (esto pasa a menudo cuando tenemos relaciones a un modelo que fue derivado). Este cacho de código define una clase abstracta SubclassedModel, cuyos descendientes tienen en objects un Manager por defecto que devuelve directamente objetos de la clase con la que fueron creados.
-
fromdjango.dbimportmodels
-fromdjango.db.models.queryimportQuerySet
-fromdjango.contrib.contenttypes.modelsimportContentType
-
-
-def_as_original_class(inst):
-"""
- Returns the instance that corresponds to `inst`
- in its original class.
- """
-model=inst.content_type.model_class()
-if(model==inst.__class__):
-returninst
-returnmodel.objects.get(id=inst.id)
-
-
-classOriginalClassQuerySet(QuerySet):
-"""
- A QuerySet that returns original classes.
- """
-def__getitem__(self,k):
-result=super(OriginalClassQuerySet,self).__getitem__(k)
-ifisinstance(result,models.Model):
-return_as_original_class(result)
-else:
-returnresult
-
-def__iter__(self):
-foriteminsuper(OriginalClassQuerySet,self).__iter__():
-yield_as_original_class(item)
-
-
-classOriginalClassManager(models.Manager):
-"""
- A Manager that fetches original classes.
- """
-defget_query_set(self):
-returnOriginalClassQuerySet(self.model)
-
-
-classSubclassedModel(models.Model):
-content_type=models.ForeignKey(ContentType,editable=False,null=True)
-objects=OriginalClassManager()
-
-classMeta:
-abstract=True
-
-defsave(self,*args,**kwargs):
-if(notself.content_type):
-self.content_type= \
-ContentType.objects.get_for_model(self.__class__)
-super(SubclassedModel,self).save(*args,**kwargs)
+
fromdjango.dbimportmodels
+fromdjango.db.models.queryimportQuerySet
+fromdjango.contrib.contenttypes.modelsimportContentType
+
+
+def_as_original_class(inst):
+"""
+ Returns the instance that corresponds to `inst`
+ in its original class.
+ """
+model=inst.content_type.model_class()
+if(model==inst.__class__):
+returninst
+returnmodel.objects.get(id=inst.id)
+
+
+classOriginalClassQuerySet(QuerySet):
+"""
+ A QuerySet that returns original classes.
+ """
+def__getitem__(self,k):
+result=super(OriginalClassQuerySet,self).__getitem__(k)
+ifisinstance(result,models.Model):
+return_as_original_class(result)
+else:
+returnresult
+
+def__iter__(self):
+foriteminsuper(OriginalClassQuerySet,self).__iter__():
+yield_as_original_class(item)
+
+
+classOriginalClassManager(models.Manager):
+"""
+ A Manager that fetches original classes.
+ """
+defget_query_set(self):
+returnOriginalClassQuerySet(self.model)
+
+
+classSubclassedModel(models.Model):
+content_type=models.ForeignKey(ContentType,editable=False,null=True)
+objects=OriginalClassManager()
+
+classMeta:
+abstract=True
+
+defsave(self,*args,**kwargs):
+if(notself.content_type):
+self.content_type= \
+ContentType.objects.get_for_model(self.__class__)
+super(SubclassedModel,self).save(*args,**kwargs)
Para usarlo, supongamos el siguente models.py en la app example:
OJO: este mecanismo deshabilita el feature de Django según el cual un modelo no tiene un Manager por defecto cuando tiene cualquier Manager explícito. Se me ocurre que eso puede romper algo en subclases de SubclassedModel si uno no lo tiene en cuenta.
diff --git a/recetario/django/testformularioconfileupload/index.html b/recetario/django/testformularioconfileupload/index.html
index cd4f2373d..f0ba7073a 100644
--- a/recetario/django/testformularioconfileupload/index.html
+++ b/recetario/django/testformularioconfileupload/index.html
@@ -28,7 +28,7 @@
client = Client()">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
Esta receta es un ejemplo sencillo de cómo enviar un email, con una parte de texto y otra binaria (adjunto)
Ejemplo:
-
# -*- coding: iso-8859-1 -*-
-fromemail.mime.textimportMIMEText
-fromemail.mime.applicationimportMIMEApplication
-fromemail.mime.multipartimportMIMEMultipart
-fromsmtplibimportSMTP
-
-msg=MIMEMultipart()
-msg['Subject']='Esto es una prueba'
-msg['From']='yo@example.com'
-msg['Reply-to']='responder-aca@example.com'
-msg['To']='vos@example.com'
-
-# Esto es lo que se ve si uno no tiene un lector de mails como la gente:
-msg.preamble='Mensaje de multiples partes.\n'
-
-# Esta es la parte textual:
-part=MIMEText("Hola, te paso un archivo interesante")
-msg.attach(part)
-
-# Esta es la parte binaria (puede ser cualquier extensión):
-part=MIMEApplication(open("factura.pdf","rb").read())
-part.add_header('Content-Disposition','attachment',filename="factura.pdf")
-msg.attach(part)
-
-# Se pueden seguir agregando partes (texto, imágenes, datos binarios, etc.)
-
-# Crear una instancia del servidor para envio de correo (hacerlo una sola vez)
-smtp=SMTP("smtp.example.com")
-# Iniciar sesión en el servidor (si es necesario):
-smtp.ehlo()
-smtp.login("yo@example.com","mipassword")
-
-# Enviar el mail (o los mails)
-smtp.sendmail(msg['From'],msg['To'],msg.as_string())
+
# -*- coding: iso-8859-1 -*-
+fromemail.mime.textimportMIMEText
+fromemail.mime.applicationimportMIMEApplication
+fromemail.mime.multipartimportMIMEMultipart
+fromsmtplibimportSMTP
+
+msg=MIMEMultipart()
+msg['Subject']='Esto es una prueba'
+msg['From']='yo@example.com'
+msg['Reply-to']='responder-aca@example.com'
+msg['To']='vos@example.com'
+
+# Esto es lo que se ve si uno no tiene un lector de mails como la gente:
+msg.preamble='Mensaje de multiples partes.\n'
+
+# Esta es la parte textual:
+part=MIMEText("Hola, te paso un archivo interesante")
+msg.attach(part)
+
+# Esta es la parte binaria (puede ser cualquier extensión):
+part=MIMEApplication(open("factura.pdf","rb").read())
+part.add_header('Content-Disposition','attachment',filename="factura.pdf")
+msg.attach(part)
+
+# Se pueden seguir agregando partes (texto, imágenes, datos binarios, etc.)
+
+# Crear una instancia del servidor para envio de correo (hacerlo una sola vez)
+smtp=SMTP("smtp.example.com")
+# Iniciar sesión en el servidor (si es necesario):
+smtp.ehlo()
+smtp.login("yo@example.com","mipassword")
+
+# Enviar el mail (o los mails)
+smtp.sendmail(msg['From'],msg['To'],msg.as_string())
diff --git a/recetario/entendiendounicode/index.html b/recetario/entendiendounicode/index.html
index e8107791a..eecd48c9b 100644
--- a/recetario/entendiendounicode/index.html
+++ b/recetario/entendiendounicode/index.html
@@ -28,7 +28,7 @@
El nivel de la en'>
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
Todo estaría de maravillas sino fuera que Encodings hay millones. Estos mapeos fueron establecidos casi independientemente en muchas empresas y países del mundo, cada uno prácticamente con el suyo. La mayoría de los Encodings usan sólo un byte (8 bits) para almacenar el número, así que sólo cabía la posibilidad de 256 símbolos, lo cual claramente no alcanza para todos los símbolos del mundo. Piensen por ejemplo en los idiomas que no usan ni siquiera como base al alfabeto latín. Así es que terminamos con cientos de Encodings llamados 'latin1', 'utf-8', 'cp-1250' y cosas más esotéricas.
Para resolver este problema es que se inventó Unicode (cualquier semejanza con http://xkcd.com/927/ es un error de concepto; ahora explico porqué). Unicode no es un encoding, aunque se asemeja mucho. Unicode es una serie de tablas de símbolos, nada más. Estos símbolos son no sólo aquellos que encontramos en todos los encodings habidos y por haber (incluyendo la mayoría de los alfabetos usados en el mundo, incluyendo el ya mencionado Braille, y hasta ficticios, como el klingon [sí, klingon, no pregunten]), sino muchos, muchos, muchos más. Demasiados, quizás. Para muestra vale un botón: http://www.fileformat.info/info/unicode/char/1f4a9/index.htm
La ventaja de Unicode es que al contener todo, es posible que, dado un Encoding, se pueden encontrar los símbolos que abarca y hacer una traducción Unicode <-> Encoding. Al paso hacia la derecha se le llama Encodeado y la inversa Decodeado. Ver Unicode en una filmina. Notar que como Unicode es más grande (o igual?) que cualquier Encoding, hay símbolos en Unicode que no están en un Encoding dado. El Encodeado de un carácter no presente en el Encoding resulta en el fatídico y über-odiado mensaje:
-
UnicodeDecodeError:'ascii'codeccan't decode byte 0xc3 in position 0: ordinal not in range(128)
+
UnicodeDecodeError:'ascii'codeccan't decode byte 0xc3 in position 0: ordinal not in range(128)
Unicode, Encodings y Python
¿Qué tiene tooooodo esto que ver con Python? Bueno, los no muy frescos de zabiola ya se habrán dado cuenta que al fin y al cabo Python corre sobre computadoras y Python maneja cadenas de caracteres (strings). Para dicho propósito Python tiene dos tipos distintos. Inicialmente, en Python2 usa el tipo unicode para representar bichos Unicode y str para representar bichos Encodeados. Esto suele traer millones de dolores de cabeza, pues el tipo str es mayormente (mal) usado en tutoriales para almacenar cadenas de caracteres, cuando se debería usar Unicode. ya explico porqué.
Para complicar las cosas[2], Python3, en cambio, tiene otros dos tipos para ello: str se usa para el almacenamiento de cadenas de caracteres Unicode y bytes para bichos Encodeados. De aquí en más seguiré con la nomenclatura de Python2; si están usando Python3, agreguen a su ensalada el hecho de que cada vez que diga unicode ustedes deben pensar en str, y cuando diga str, ustedes piensen en bytes. Cuando Python3 sea más utilizado, y si aún estoy vivo y con uso de mis facultades, volveré a esta página y les juro que pongo todo en nomenclatura Python3.
Entonces, tamos listoso0 con la nomenclatura: unicode para bichos Unicode y str para bichos Encodeados. La forma de crear un bicho Unicode es muy simple[1]:
-
a=u'Aló mundo!'
+
a=u'Aló mundo!'
El source también existe, y está encodeado
¿Vieron ese [1] que puse más arriba? Bueno, resulta que hay una mentira casi tan grande como una casa en todo esto. Más que una mentira, una vuelta más de rosca. ¿Vieron que dije que cuando uno deja el mundo Python/Unicode uno pasa al mundo Encodeado? Bueno, les cuento, y agárrensé: Los archivos que contienen el código fuente de su programa Python también están Encodeados. Esto trae como consecuencia...
-
# -*- coding: utf-8 -*-
+
# -*- coding: utf-8 -*-
Ver también:
diff --git a/recetario/estilosrst2pdf/index.html b/recetario/estilosrst2pdf/index.html
index 7304b1e2a..47c819a46 100644
--- a/recetario/estilosrst2pdf/index.html
+++ b/recetario/estilosrst2pdf/index.html
@@ -33,7 +33,7 @@
En el svn de rst2pdf se puede ver un archivo de ejemplo, que define todos los atributos posibles.
En rst2pdf un estilo (est">
-
+
Ir al contenido principal
@@ -67,12 +67,12 @@
diff --git a/recetario/extraermails/index.html b/recetario/extraermails/index.html
index 2f7fd3352..8aa555353 100644
--- a/recetario/extraermails/index.html
+++ b/recetario/extraermails/index.html
@@ -29,7 +29,7 @@
El código anterior devuelve una lista de strings, donde cada string es una ">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
El código anterior devuelve una lista de strings, donde cada string es una dirección de email. El texto original puede contener basura como espacios, comas u otros caracteres.
diff --git a/recetario/facturapyfpdf/index.html b/recetario/facturapyfpdf/index.html
index f939fe21a..e8fa458e0 100644
--- a/recetario/facturapyfpdf/index.html
+++ b/recetario/facturapyfpdf/index.html
@@ -26,7 +26,7 @@
Esta receta es un ejemplo sencillo de cómo generar una factura en PDF utilizando la libreria PyFpdf (port de FPDF para python).
Para más detalles sobre la libreria PyFpdf y bajar una versi">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/recetario/fun/minispaceinvaders/index.html b/recetario/fun/minispaceinvaders/index.html
index aeedda092..163b4b0ee 100644
--- a/recetario/fun/minispaceinvaders/index.html
+++ b/recetario/fun/minispaceinvaders/index.html
@@ -26,7 +26,7 @@
La nave y el bicho se mueven solos de fo">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Este script permite enviar emails a través de GMail. Los emails pueden tener texto plano, HTML y archivos adjuntos (todos opcionales).
Nota: El script lo escribí originalmente en inglés. Debería entenderse, pero pienso traducirlo cuando tenga algo más de tiempo.
Archivo: GmailMail.py
-
#!/usr/bin/env python
-
-# requires Python >= 2.5
-importsmtplib
-fromemail.mime.multipartimportMIMEMultipart
-fromemail.mime.baseimportMIMEBase
-fromemail.mime.textimportMIMEText
-fromemail.mime.audioimportMIMEAudio
-fromemail.mime.imageimportMIMEImage
-fromemail.encodersimportencode_base64
-frommimetypesimportguess_type
-fromos.pathimportbasename
-
-classGmailMail():
-def__init__(self,gmail_user,gmail_pwd):
-"""
- Prepares an instance with basic authentication
-
- """
-self.gmail_user=gmail_user
-self.gmail_pwd=gmail_pwd
-
-defgetAttachment(self,path,charset='ASCII'):
-contentType,encoding=guess_type(path)
-
-ifcontentTypeisNoneorencodingisnotNone:
-contentType='application/octet-stream'
-
-mainType,subType=contentType.split('/',1)
-_file=open(path,'rb')
-
-ifmainType=='text':
-attachment=MIMEText(_file.read(),subType,charset)
-elifmainType=='message':
-attachment=email.message_from_file(_file)
-elifmainType=='image':
-attachment=MIMEImage(_file.read(),_subType=subType)
-elifmainType=='audio':
-attachment=MIMEAudio(_file.read(),_subType=subType)
-else:
-attachment=MIMEBase(mainType,subType)
-attachment.set_payload(_file.read())
-encode_base64(attachment)
-
-_file.close()
-
-attachment.add_header('Content-Disposition','attachment',
-filename=basename(path))
-
-returnattachment
-
-defsend(self,to,subject,text=u"",html=None,attachments=None,charset="iso-8859-15"):
-"""
- Sends an email through Gmail using the authentication
- given to this instance.
-
- If given, attachments must be a list of paths pointing
- to the files we want to include.
-
- This script does not embed inline content (multipart/related)
-
- """
-ifcharsetin['utf8','utf-8']:#bug?
-fromemail.charsetimportadd_charset,SHORTEST
-add_charset('utf-8',SHORTEST,None,None)
-
-ifisinstance(text,unicode):
-text=text.encode(charset,'replace')
-
-ifisinstance(html,unicode):
-html=html.encode(charset,'replace')
-
-ifattachmentsisNone:
-attachments=[]
-
-iftext:plain_part=MIMEText(text,'plain',charset)
-ifhtml:html_part=MIMEText(html,'html',charset)
-
-is_alternative=htmlandtext
-layers=[]
-ifattachmentsoris_alternative:
-msg=MIMEMultipart()#mixed
-msg.set_charset(charset)
-msg.preamble='This is a multi-part message in MIME format.'
-msg.epilogue=''
-layers.append(msg)
-
-ifis_alternative:
-msgAlternative=MIMEMultipart('alternative')
-msg.attach(msgAlternative)
-layers.append(msgAlternative)
-
-iftext:
-layers[-1].attach(plain_part)
-ifhtml:
-layers[-1].attach(html_part)
-
-eliftext:
-msg=plain_part
-else:#html only
-msg=html_part
-
-forpathinattachments:
-msg.attach(self.getAttachment(path,charset))
-
-msg['From']=self.gmail_user
-msg['To']=to
-msg['Subject']=subject
-
-mailServer=smtplib.SMTP("smtp.gmail.com",587)
-mailServer.ehlo()
-mailServer.starttls()
-mailServer.ehlo()
-mailServer.login(self.gmail_user,self.gmail_pwd)
-mailServer.sendmail(self.gmail_user,to,msg.as_string())
-# Should be mailServer.quit(), but that crashes...
-mailServer.close()
+
#!/usr/bin/env python
+
+# requires Python >= 2.5
+importsmtplib
+fromemail.mime.multipartimportMIMEMultipart
+fromemail.mime.baseimportMIMEBase
+fromemail.mime.textimportMIMEText
+fromemail.mime.audioimportMIMEAudio
+fromemail.mime.imageimportMIMEImage
+fromemail.encodersimportencode_base64
+frommimetypesimportguess_type
+fromos.pathimportbasename
+
+classGmailMail():
+def__init__(self,gmail_user,gmail_pwd):
+"""
+ Prepares an instance with basic authentication
+
+ """
+self.gmail_user=gmail_user
+self.gmail_pwd=gmail_pwd
+
+defgetAttachment(self,path,charset='ASCII'):
+contentType,encoding=guess_type(path)
+
+ifcontentTypeisNoneorencodingisnotNone:
+contentType='application/octet-stream'
+
+mainType,subType=contentType.split('/',1)
+_file=open(path,'rb')
+
+ifmainType=='text':
+attachment=MIMEText(_file.read(),subType,charset)
+elifmainType=='message':
+attachment=email.message_from_file(_file)
+elifmainType=='image':
+attachment=MIMEImage(_file.read(),_subType=subType)
+elifmainType=='audio':
+attachment=MIMEAudio(_file.read(),_subType=subType)
+else:
+attachment=MIMEBase(mainType,subType)
+attachment.set_payload(_file.read())
+encode_base64(attachment)
+
+_file.close()
+
+attachment.add_header('Content-Disposition','attachment',
+filename=basename(path))
+
+returnattachment
+
+defsend(self,to,subject,text=u"",html=None,attachments=None,charset="iso-8859-15"):
+"""
+ Sends an email through Gmail using the authentication
+ given to this instance.
+
+ If given, attachments must be a list of paths pointing
+ to the files we want to include.
+
+ This script does not embed inline content (multipart/related)
+
+ """
+ifcharsetin['utf8','utf-8']:#bug?
+fromemail.charsetimportadd_charset,SHORTEST
+add_charset('utf-8',SHORTEST,None,None)
+
+ifisinstance(text,unicode):
+text=text.encode(charset,'replace')
+
+ifisinstance(html,unicode):
+html=html.encode(charset,'replace')
+
+ifattachmentsisNone:
+attachments=[]
+
+iftext:plain_part=MIMEText(text,'plain',charset)
+ifhtml:html_part=MIMEText(html,'html',charset)
+
+is_alternative=htmlandtext
+layers=[]
+ifattachmentsoris_alternative:
+msg=MIMEMultipart()#mixed
+msg.set_charset(charset)
+msg.preamble='This is a multi-part message in MIME format.'
+msg.epilogue=''
+layers.append(msg)
+
+ifis_alternative:
+msgAlternative=MIMEMultipart('alternative')
+msg.attach(msgAlternative)
+layers.append(msgAlternative)
+
+iftext:
+layers[-1].attach(plain_part)
+ifhtml:
+layers[-1].attach(html_part)
+
+eliftext:
+msg=plain_part
+else:#html only
+msg=html_part
+
+forpathinattachments:
+msg.attach(self.getAttachment(path,charset))
+
+msg['From']=self.gmail_user
+msg['To']=to
+msg['Subject']=subject
+
+mailServer=smtplib.SMTP("smtp.gmail.com",587)
+mailServer.ehlo()
+mailServer.starttls()
+mailServer.ehlo()
+mailServer.login(self.gmail_user,self.gmail_pwd)
+mailServer.sendmail(self.gmail_user,to,msg.as_string())
+# Should be mailServer.quit(), but that crashes...
+mailServer.close()
Algunos tests (ejemplos, casos de uso):
Archivo: GmailMail_tests.py
-
# -*- coding: utf-8 -*-
-
-fromGmailMailimportGmailMail
-fromurllib2importurlopen
-
-text=u"""\
-Éste es el contenido en modo texto plano
-Tenemos acentos y eñes.
-
-"""
-url="http://python.com.ar/moin"
-html=urlopen(url).read()
-
-user='XXXXXX@gmail.com'# mi usuario de GMail
-pwd='********'# mi contraseña de GMail
-
-m=GmailMail(user,pwd)
-
-print"mandando texto plano solamente"
-m.send(user,u'prueba de sólo texto',text)
-
-print"mandando html solamente"
-m.send(user,u'prueba con sólo html',html=html)
-
-print"mandando texto plano y html (sin attachments)"
-m.send(user,u'prueba con texto plano y html (sin attachments)',text,html)
-
-print"mandando texto plano y attachments"
-m.send(user,u'prueba con texto plano y attachments',text,attachments=['GmailMail.py'])
-
-print"mandando html y attachments"
-m.send(user,u'prueba con html y attachments',html=html,attachments=['GmailMail.py'])
-
-print"mandando attachments solamente"
-m.send(user,u'prueba con attachments solamente',attachments=['GmailMail.py'])
-
-print"mandando todo"
-m.send(user,u'prueba con todo',text,html,attachments=['GmailMail.py'])
+
# -*- coding: utf-8 -*-
+
+fromGmailMailimportGmailMail
+fromurllib2importurlopen
+
+text=u"""\
+Éste es el contenido en modo texto plano
+Tenemos acentos y eñes.
+
+"""
+url="http://python.com.ar/moin"
+html=urlopen(url).read()
+
+user='XXXXXX@gmail.com'# mi usuario de GMail
+pwd='********'# mi contraseña de GMail
+
+m=GmailMail(user,pwd)
+
+print"mandando texto plano solamente"
+m.send(user,u'prueba de sólo texto',text)
+
+print"mandando html solamente"
+m.send(user,u'prueba con sólo html',html=html)
+
+print"mandando texto plano y html (sin attachments)"
+m.send(user,u'prueba con texto plano y html (sin attachments)',text,html)
+
+print"mandando texto plano y attachments"
+m.send(user,u'prueba con texto plano y attachments',text,attachments=['GmailMail.py'])
+
+print"mandando html y attachments"
+m.send(user,u'prueba con html y attachments',html=html,attachments=['GmailMail.py'])
+
+print"mandando attachments solamente"
+m.send(user,u'prueba con attachments solamente',attachments=['GmailMail.py'])
+
+print"mandando todo"
+m.send(user,u'prueba con todo',text,html,attachments=['GmailMail.py'])
Referencias (que recuerdo):
diff --git a/recetario/gtkontk/index.html b/recetario/gtkontk/index.html
index df8314e81..8de06e170 100644
--- a/recetario/gtkontk/index.html
+++ b/recetario/gtkontk/index.html
@@ -26,7 +26,7 @@
Foto de Pantalla:
De fondo Gedit en Ubuntu, usando el tema Ambiance, arriba una ventana con similar tema pero en TK">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
El codigo de este ejemplo esta mas abajo (la foto no esta editada, no hay truco, funciona en KDE, o inclusive lo he hecho funcionar sin GTK instalado).
Descripcion: Crea 2 ventanas pequeñas iguales, una tratara de imitar el tema de GTK, la otra se mostrara como es por defecto.
(el ejemplo funciona en Ubuntu, que es lo que yo uso, usa el codigo de arriba, lejos de estar bien hecho, pero sirve de ejemplo).
-
#
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-#import this
-#import antigravity
-importcolour# <-------Aca esta la magia
-importtkFont
-fromTkinterimport*
-#
-root=Tk()
-root.title('GTK Themes on TK: Demo')
-root.wm_attributes("-alpha",1)
-root.focus()
-root.resizable(0,0)
-# Muestra informacion
-print" GTK-On-TK Theme Hack:"
-print" I will try to mimic: "+colour.get_Gtk_Theme_Name()+" GTK Theme"
-print" By Parsing the file: "+colour.get_Gtk_Theme_Path()
-print" This is not perfect, if you are on KDE install QTCurve... "
-# Menubar con GTK
-menubar=Menu(root,bd=0,relief=FLAT,fg=str(colour.get_color_scheme_item('base_color')),bg=str(colour.get_color_scheme_item('text_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
-filemenu=Menu(menubar,tearoff=0,bd=0,relief=FLAT,fg=str(colour.get_color_scheme_item('base_color')),bg=str(colour.get_color_scheme_item('text_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
-filemenu.add_command(label="Nuevo",state='disabled')
-filemenu.add_separator()
-filemenu.add_command(label="Cerrar ✗",command=lambda:root.destroy())
-menubar.add_cascade(label="Archivo",menu=filemenu)
-root.config(menu=menubar)
-# GUI con GTK
-root.config(bg=str(colour.get_color_scheme_item('base_color')))
-labl1=Label(root,text="Soy una ventana con Tema GTK",font=("Times",12,'bold'),bd=0,relief=FLAT,bg=str(colour.get_color_scheme_item('base_color')),fg=str(colour.get_color_scheme_item('text_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
-labl1.pack(side=TOP,expand='YES',fill='x',pady=10,padx=20)
-button=Button(root,text="Soy Linda!",fg=str(colour.get_color_scheme_item('text_color')),bd=0,relief=FLAT,bg=str(colour.get_color_scheme_item('base_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
-button.pack(side=BOTTOM,pady=10,padx=10)
-# la misma GUI pero como es por defecto
-toplevel=Toplevel()
-menubarz=Menu(toplevel)
-filemenuz=Menu(toplevel,tearoff=0)
-filemenuz.add_command(label="Nuevo",state='disabled')
-filemenuz.add_separator()
-filemenuz.add_command(label="Cerrar ✗",command=lambda:root.destroy())
-menubarz.add_cascade(label="Archivo",menu=filemenuz)
-toplevel.config(menu=menubarz)
-labl2=Label(toplevel,text="Soy una ventana SIN Tema GTK")
-labl2.pack(side=TOP,expand='YES',fill='x',pady=10,padx=20)
-button2=Button(toplevel,text="Soy Fea!")
-button2.pack(side=BOTTOM,pady=10,padx=10)
-# Le pongo fuente de Ubuntu (se puede omitir)
-menubar.config(font=("ubuntu",10,"normal","roman"))
-labl1.config(font=("ubuntu",10,"bold","roman"))
-filemenu.config(font=("ubuntu",10,"normal","roman"))
-button.config(font=("ubuntu",10,"bold","roman"))
-#
-root.mainloop()
+
#
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+#import this
+#import antigravity
+importcolour# <-------Aca esta la magia
+importtkFont
+fromTkinterimport*
+#
+root=Tk()
+root.title('GTK Themes on TK: Demo')
+root.wm_attributes("-alpha",1)
+root.focus()
+root.resizable(0,0)
+# Muestra informacion
+print" GTK-On-TK Theme Hack:"
+print" I will try to mimic: "+colour.get_Gtk_Theme_Name()+" GTK Theme"
+print" By Parsing the file: "+colour.get_Gtk_Theme_Path()
+print" This is not perfect, if you are on KDE install QTCurve... "
+# Menubar con GTK
+menubar=Menu(root,bd=0,relief=FLAT,fg=str(colour.get_color_scheme_item('base_color')),bg=str(colour.get_color_scheme_item('text_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
+filemenu=Menu(menubar,tearoff=0,bd=0,relief=FLAT,fg=str(colour.get_color_scheme_item('base_color')),bg=str(colour.get_color_scheme_item('text_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
+filemenu.add_command(label="Nuevo",state='disabled')
+filemenu.add_separator()
+filemenu.add_command(label="Cerrar ✗",command=lambda:root.destroy())
+menubar.add_cascade(label="Archivo",menu=filemenu)
+root.config(menu=menubar)
+# GUI con GTK
+root.config(bg=str(colour.get_color_scheme_item('base_color')))
+labl1=Label(root,text="Soy una ventana con Tema GTK",font=("Times",12,'bold'),bd=0,relief=FLAT,bg=str(colour.get_color_scheme_item('base_color')),fg=str(colour.get_color_scheme_item('text_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
+labl1.pack(side=TOP,expand='YES',fill='x',pady=10,padx=20)
+button=Button(root,text="Soy Linda!",fg=str(colour.get_color_scheme_item('text_color')),bd=0,relief=FLAT,bg=str(colour.get_color_scheme_item('base_color')),activebackground=str(colour.get_color_scheme_item('selected_bg_color')),activeforeground=str(colour.get_color_scheme_item('text_color')))
+button.pack(side=BOTTOM,pady=10,padx=10)
+# la misma GUI pero como es por defecto
+toplevel=Toplevel()
+menubarz=Menu(toplevel)
+filemenuz=Menu(toplevel,tearoff=0)
+filemenuz.add_command(label="Nuevo",state='disabled')
+filemenuz.add_separator()
+filemenuz.add_command(label="Cerrar ✗",command=lambda:root.destroy())
+menubarz.add_cascade(label="Archivo",menu=filemenuz)
+toplevel.config(menu=menubarz)
+labl2=Label(toplevel,text="Soy una ventana SIN Tema GTK")
+labl2.pack(side=TOP,expand='YES',fill='x',pady=10,padx=20)
+button2=Button(toplevel,text="Soy Fea!")
+button2.pack(side=BOTTOM,pady=10,padx=10)
+# Le pongo fuente de Ubuntu (se puede omitir)
+menubar.config(font=("ubuntu",10,"normal","roman"))
+labl1.config(font=("ubuntu",10,"bold","roman"))
+filemenu.config(font=("ubuntu",10,"normal","roman"))
+button.config(font=("ubuntu",10,"bold","roman"))
+#
+root.mainloop()
Comentario personal:
Es más bonito que TTK 🙂. Como sea, la idea es aprovechar que en Linux TODO es un archivo, la magia esta en parsear.
importgtk
-
-classComplete(gtk.Entry):
-'''a class to autocomplete'''
-
-def__init__(self,*words):
-gtk.Entry.__init__(self)
-self.completion=gtk.EntryCompletion()
-self.set_completion(self.completion)
-self.model=gtk.ListStore(str)
-self.completion.set_model(self.model)
-self.completion.set_text_column(0)
-
-forwordinwords:
-self.remember(word)
-
-defremember(self,value):
-'''add a value to the list of strings to suggest'''
-self.model.append([value])
-
-if__name__=='__main__':
-window=gtk.Window()
-complete=Complete("python","pyar","span","eggs")
-window.add(complete)
-window.connect('delete-event',gtk.main_quit)
-window.show_all()
-gtk.main()
+
importgtk
+
+classComplete(gtk.Entry):
+'''a class to autocomplete'''
+
+def__init__(self,*words):
+gtk.Entry.__init__(self)
+self.completion=gtk.EntryCompletion()
+self.set_completion(self.completion)
+self.model=gtk.ListStore(str)
+self.completion.set_model(self.model)
+self.completion.set_text_column(0)
+
+forwordinwords:
+self.remember(word)
+
+defremember(self,value):
+'''add a value to the list of strings to suggest'''
+self.model.append([value])
+
+if__name__=='__main__':
+window=gtk.Window()
+complete=Complete("python","pyar","span","eggs")
+window.add(complete)
+window.connect('delete-event',gtk.main_quit)
+window.show_all()
+gtk.main()
diff --git a/recetario/gui/gtk/browserconwebinspector/index.html b/recetario/gui/gtk/browserconwebinspector/index.html
index 5a7cb5435..189cd20af 100644
--- a/recetario/gui/gtk/browserconwebinspector/index.html
+++ b/recetario/gui/gtk/browserconwebinspector/index.html
@@ -26,7 +26,7 @@
En este caso vemos cómo agregar el web inspector para inspeccionar y debuggear la página que estamos viendo.
El resultado '>
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Este ejemplo muestra cómo usar un contenedor de botones para agregar botones, hacer que mantengan su forma óptima y se distribuyan por la pantalla de manera homogénea.
Ejemplo de cómo solicitar una confirmación de cierre en una ventana.
-
importsys
-importgtk
-
-classVentanaPrincipal(gtk.Window):
-'''la ventana principal'''
-
-def__init__(self):
-'''constructor'''
-gtk.Window.__init__(self)
-self.set_default_size(300,200)
-self.set_title('Ejemplo')
-
-label=gtk.Label('cerrame')
-label.show()
-
-self.add(label)
-self.connect('delete-event',self._on_close)
-
-def_on_close(self,widget,event):
-'''metodo llamado cuando aprietan el boton cerrar'''
-ifnotself.confirmar_cierre():
-returnTrue
-else:
-sys.exit(0)
-
-defconfirmar_cierre(self):
-'''muestra un dialogo que pregunta si esta seguro que
- quiere cerrar, devuelve True si selecciona si'''
-dialogo=gtk.MessageDialog(self,type=gtk.MESSAGE_QUESTION,
-buttons=gtk.BUTTONS_YES_NO,
-message_format="Esta seguro que desea salir?")
-
-response=dialogo.run()
-dialogo.hide()
-
-ifresponse==gtk.RESPONSE_YES:
-returnTrue
-
-returnFalse
-
-
-deftest():
-'''prueba la implementacion'''
-ventana=VentanaPrincipal()
-ventana.show()
-gtk.main()
-
-if__name__=='__main__':
-test()
+
importsys
+importgtk
+
+classVentanaPrincipal(gtk.Window):
+'''la ventana principal'''
+
+def__init__(self):
+'''constructor'''
+gtk.Window.__init__(self)
+self.set_default_size(300,200)
+self.set_title('Ejemplo')
+
+label=gtk.Label('cerrame')
+label.show()
+
+self.add(label)
+self.connect('delete-event',self._on_close)
+
+def_on_close(self,widget,event):
+'''metodo llamado cuando aprietan el boton cerrar'''
+ifnotself.confirmar_cierre():
+returnTrue
+else:
+sys.exit(0)
+
+defconfirmar_cierre(self):
+'''muestra un dialogo que pregunta si esta seguro que
+ quiere cerrar, devuelve True si selecciona si'''
+dialogo=gtk.MessageDialog(self,type=gtk.MESSAGE_QUESTION,
+buttons=gtk.BUTTONS_YES_NO,
+message_format="Esta seguro que desea salir?")
+
+response=dialogo.run()
+dialogo.hide()
+
+ifresponse==gtk.RESPONSE_YES:
+returnTrue
+
+returnFalse
+
+
+deftest():
+'''prueba la implementacion'''
+ventana=VentanaPrincipal()
+ventana.show()
+gtk.main()
+
+if__name__=='__main__':
+test()
diff --git a/recetario/gui/gtk/dialog/index.html b/recetario/gui/gtk/dialog/index.html
index 245799dc7..ce17ec823 100644
--- a/recetario/gui/gtk/dialog/index.html
+++ b/recetario/gui/gtk/dialog/index.html
@@ -29,7 +29,7 @@
# por defecto crea un mensaje de informacion sin botones
info = gtk.MessageDialog(message_format="i'>
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
Ejemplo para crear diálogos modales de distintos tipos con distintos botones.
-
importgtk
-importsys
-
-# por defecto crea un mensaje de informacion sin botones
-info=gtk.MessageDialog(message_format="informacion!")
-# tipo advertencia con un boton de ok
-warning=gtk.MessageDialog(type=gtk.MESSAGE_WARNING,
-buttons=gtk.BUTTONS_OK_CANCEL,message_format="advertencia..")
-# pregunta con botones si no
-question=gtk.MessageDialog(type=gtk.MESSAGE_QUESTION,
-buttons=gtk.BUTTONS_YES_NO,message_format="pregunta?")
-# error con boton ok
-error=gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
-buttons=gtk.BUTTONS_OK,message_format="error!?!")
-
-# run bloquea hasta que se produzca un evento y devuelve el valor del evento
-ifinfo.run()==gtk.RESPONSE_DELETE_EVENT:
-print"si, es la unica senial que puede emitir, ya que no tiene botones"
-# hay que esconder el dialogo
-info.hide()
-
-# almacenamos el valor de retorno en una variable para controlar varios valores
-response=warning.run()
-warning.hide()
-
-ifresponse==gtk.RESPONSE_OK:
-print"advertencia respondio aceptar"
-elifresponse==gtk.RESPONSE_CANCEL:
-print"advertencia respondio cancel"
-
-response=question.run()
-
-ifresponse==gtk.RESPONSE_YES:
-print"respondio si!"
-elifresponse==gtk.RESPONSE_NO:
-print"respondio no :("
-
-question.hide()
-
-iferror.run()==gtk.RESPONSE_OK:
-print"error OK"
-
-error.hide()
-sys.exit(0)
-
-gtk.main()
+
importgtk
+importsys
+
+# por defecto crea un mensaje de informacion sin botones
+info=gtk.MessageDialog(message_format="informacion!")
+# tipo advertencia con un boton de ok
+warning=gtk.MessageDialog(type=gtk.MESSAGE_WARNING,
+buttons=gtk.BUTTONS_OK_CANCEL,message_format="advertencia..")
+# pregunta con botones si no
+question=gtk.MessageDialog(type=gtk.MESSAGE_QUESTION,
+buttons=gtk.BUTTONS_YES_NO,message_format="pregunta?")
+# error con boton ok
+error=gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
+buttons=gtk.BUTTONS_OK,message_format="error!?!")
+
+# run bloquea hasta que se produzca un evento y devuelve el valor del evento
+ifinfo.run()==gtk.RESPONSE_DELETE_EVENT:
+print"si, es la unica senial que puede emitir, ya que no tiene botones"
+# hay que esconder el dialogo
+info.hide()
+
+# almacenamos el valor de retorno en una variable para controlar varios valores
+response=warning.run()
+warning.hide()
+
+ifresponse==gtk.RESPONSE_OK:
+print"advertencia respondio aceptar"
+elifresponse==gtk.RESPONSE_CANCEL:
+print"advertencia respondio cancel"
+
+response=question.run()
+
+ifresponse==gtk.RESPONSE_YES:
+print"respondio si!"
+elifresponse==gtk.RESPONSE_NO:
+print"respondio no :("
+
+question.hide()
+
+iferror.run()==gtk.RESPONSE_OK:
+print"error OK"
+
+error.hide()
+sys.exit(0)
+
+gtk.main()
diff --git a/recetario/gui/gtk/emuladorterminal/index.html b/recetario/gui/gtk/emuladorterminal/index.html
index dab7def9e..51889987e 100644
--- a/recetario/gui/gtk/emuladorterminal/index.html
+++ b/recetario/gui/gtk/emuladorterminal/index.html
@@ -33,7 +33,7 @@
scroll = gtk.Scrol'>
-
+
Ir al contenido principal
@@ -67,12 +67,12 @@
diff --git a/recetario/gui/gtk/entry/index.html b/recetario/gui/gtk/entry/index.html
index 4f707ae9e..6518be690 100644
--- a/recetario/gui/gtk/entry/index.html
+++ b/recetario/gui/gtk/entry/index.html
@@ -30,7 +30,7 @@
class Ventana(gtk.Window):
'''clase que define una ve">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
Crear una ventana con un label, un campo de texto y mostrar el mensaje hola nombre con el valor ingresado en el entry.
-
importgtk
-importsys
-
-classVentana(gtk.Window):
-'''clase que define una ventana que saluda'''
-
-def__init__(self):
-'''constructor, se llama al constructor de la clase padre'''
-gtk.Window.__init__(self)
-
-# un tamanio muy chico para que se expanda el minimo tamanio necesario
-self.set_default_size(10,10)
-self.label=gtk.Label("nombre")
-self.entry=gtk.Entry()
-self.set_title("entry")
-# 5 pixeles de espacio entre el borde de la ventana y el primer
-# contenedor
-self.set_border_width(5)
-
-# 5 pixeles de espaciado entre cada widget
-hbox=gtk.HBox(spacing=5)
-hbox.pack_start(self.label)
-hbox.pack_start(self.entry)
-
-self.add(hbox)
-hbox.show_all()
-
-self.connect("delete-event",self.on_delete)
-# conectamos la senial activate (el usuario presiona enter)
-self.entry.connect("activate",self.on_entry_activate)
-
-defon_delete(self,window,event):
-'''llamado cuando se cierra la ventana'''
-sys.exit(0)
-
-defon_entry_activate(self,entry):
-'''llamada cuando se presiona enter en el entry, el primer elemento
- de toda senial de gtk es el elemento que emite la senial, asi que no
- necesitamos tener una referencia al elemento para interactuar con el'''
-message=gtk.MessageDialog(buttons=gtk.BUTTONS_OK,
-message_format="hola "+entry.get_text())
-message.run()
-message.hide()
-
-if__name__=="__main__":
-hola=Ventana()
-hola.show()
-gtk.main()
+
importgtk
+importsys
+
+classVentana(gtk.Window):
+'''clase que define una ventana que saluda'''
+
+def__init__(self):
+'''constructor, se llama al constructor de la clase padre'''
+gtk.Window.__init__(self)
+
+# un tamanio muy chico para que se expanda el minimo tamanio necesario
+self.set_default_size(10,10)
+self.label=gtk.Label("nombre")
+self.entry=gtk.Entry()
+self.set_title("entry")
+# 5 pixeles de espacio entre el borde de la ventana y el primer
+# contenedor
+self.set_border_width(5)
+
+# 5 pixeles de espaciado entre cada widget
+hbox=gtk.HBox(spacing=5)
+hbox.pack_start(self.label)
+hbox.pack_start(self.entry)
+
+self.add(hbox)
+hbox.show_all()
+
+self.connect("delete-event",self.on_delete)
+# conectamos la senial activate (el usuario presiona enter)
+self.entry.connect("activate",self.on_entry_activate)
+
+defon_delete(self,window,event):
+'''llamado cuando se cierra la ventana'''
+sys.exit(0)
+
+defon_entry_activate(self,entry):
+'''llamada cuando se presiona enter en el entry, el primer elemento
+ de toda senial de gtk es el elemento que emite la senial, asi que no
+ necesitamos tener una referencia al elemento para interactuar con el'''
+message=gtk.MessageDialog(buttons=gtk.BUTTONS_OK,
+message_format="hola "+entry.get_text())
+message.run()
+message.hide()
+
+if__name__=="__main__":
+hola=Ventana()
+hola.show()
+gtk.main()
diff --git a/recetario/gui/gtk/entrysolonumeros/index.html b/recetario/gui/gtk/entrysolonumeros/index.html
index 18eb90c32..a192b0b68 100644
--- a/recetario/gui/gtk/entrysolonumeros/index.html
+++ b/recetario/gui/gtk/entrysolonumeros/index.html
@@ -24,7 +24,7 @@
-
+
Ir al contenido principal
@@ -58,12 +58,12 @@
Este ejemplo muestra como permitir el ingreso de solo números en un gtk.Entry, a través de la señal insert-text de gtk.Editable (clase de la que hereda gtk.Entry) y usando el método stop_emission de gobject para evitar que la señal se propague y sea manejada por el handler por defecto para la señal (que es el que inserta el carácter en el widget)
-
'''ejemplo sobre solo dejar ingresar numeros en un campo de text
-tambien sirve para cadenas de texto pegadas en el entry con ctrl-v
-'''
-
-importre
-importgtk
-
-ONLY_NUMBERS=re.compile('^[0-9]*$')
-
-defon_insert_text(editable,new_text,new_text_length,position):
-'''called when text is inserted on an entry'''
-ifONLY_NUMBERS.match(new_text)isNone:
-editable.stop_emission('insert-text')
-
-entry=gtk.Entry()
-entry.connect('insert-text',on_insert_text)
-window=gtk.Window()
-window.set_title('only numbers')
-window.add(entry)
-window.connect('delete-event',gtk.main_quit)
-window.show_all()
-
-gtk.main()
+
'''ejemplo sobre solo dejar ingresar numeros en un campo de text
+tambien sirve para cadenas de texto pegadas en el entry con ctrl-v
+'''
+
+importre
+importgtk
+
+ONLY_NUMBERS=re.compile('^[0-9]*$')
+
+defon_insert_text(editable,new_text,new_text_length,position):
+'''called when text is inserted on an entry'''
+ifONLY_NUMBERS.match(new_text)isNone:
+editable.stop_emission('insert-text')
+
+entry=gtk.Entry()
+entry.connect('insert-text',on_insert_text)
+window=gtk.Window()
+window.set_title('only numbers')
+window.add(entry)
+window.connect('delete-event',gtk.main_quit)
+window.show_all()
+
+gtk.main()
diff --git a/recetario/gui/gtk/erorhandler/index.html b/recetario/gui/gtk/erorhandler/index.html
index c2a254ee1..f26759276 100644
--- a/recetario/gui/gtk/erorhandler/index.html
+++ b/recetario/gui/gtk/erorhandler/index.html
@@ -24,7 +24,7 @@
-
+
Ir al contenido principal
@@ -58,12 +58,12 @@
Si aplicamos el decorador error_handler a una función, cuando lance una excepción, vamos a obtener un diálogo modal mostrandomos el traceback. Recomiendo usarlo solo para debug o versiones beta, un usuario no debería ver el traceback crudo.
func(*args, **kwargs) será llamada en un thread aparte el cuál será monitoreado periódicamente por su finalización. Una vez terminado llamará a callback pasándole una tupla cuyo primer elemento es True sí la función término con éxito y False sí la función lanzo una excepción. El segundo elemento de la tupla es el valor retornado por la función si tuvo éxito o la excepción lanzada en caso que haya fallado.
Obviamente en la función esa no pueden correr código relacionado con gtk
-
'''example of a generic function to run a given function in a thread and call a
-callback in the main thread with the result of the function'''
-
-importgtk
-importglib
-importtime
-importQueue
-importurllib
-importthreading
-
-# this is the important function, copy this to your project to reuse it
-defrun_in_thread(callback,func,*args,**kwargs):
-'''run *func* in a thread with *args* and *kwargs* as arguments, when
- finished call callback with a two item tuple containing a boolean as first
- item informing if the function returned correctly and the returned value or
- the exception thrown as second item
- '''
-
-queue=Queue.Queue()
-
-defrun():
-'''
- main function of the thread, run func with args and kwargs
- and get the result, call callback with the (True, result)
-
- if an exception is thrown call callback with (False, exception)
- '''
-try:
-result=(True,func(*args,**kwargs))
-exceptException,ex:
-result=(False,ex)
-
-queue.put(result)
-
-defcheck():
-'''
- check if func finished
- '''
-try:
-result=queue.get(False,0.1)
-exceptQueue.Empty:
-returnTrue
-
-callback(result)
-returnFalse
-
-glib.timeout_add_seconds(1,check)
-thread=threading.Thread(target=run)
-thread.setDaemon(True)
-thread.start()
-
-# everything below is just for the demo
-defmain():
-'''
- main function called when the module is run from the command line
- '''
-
-defload_site(url):
-'''
- a demo function that loads the content of a url
- '''
-returnurllib.urlopen(url).read()
-
-classDisplay(gtk.Window):
-'''
- a window to display some content that loads slowly
- '''
-
-def__init__(self,text,func,*args,**kwargs):
-gtk.Window.__init__(self)
-self.set_default_size(400,300)
-self.set_title("display")
-self.set_border_width(2)
-
-self.func=func
-self.args=args
-self.kwargs=kwargs
-
-vbox=gtk.VBox(spacing=2)
-scroll=gtk.ScrolledWindow()
-self.text=gtk.TextView()
-self.text.get_buffer().set_text(text)
-
-scroll.add(self.text)
-
-vbox.pack_start(scroll,True,True)
-
-self.loading=gtk.ProgressBar()
-self.is_loading=False
-
-vbox.pack_start(self.loading,False)
-
-buttons=gtk.HButtonBox()
-self.run=gtk.Button(stock=gtk.STOCK_EXECUTE)
-self.run.connect('clicked',self._on_run_clicked)
-buttons.pack_start(self.run)
-
-vbox.pack_start(buttons,False)
-
-self.add(vbox)
-
-vbox.show_all()
-self.loading.hide()
-self.connect("delete-event",gtk.main_quit)
-
-def_on_run_clicked(self,button):
-self.set_loading()
-run_in_thread(self._on_result_ready,self.func,*self.args,
-**self.kwargs)
-
-defset_loading(self,is_loading=True):
-'''
- set the window to the loading state
- '''
-self.is_loading=is_loading
-self.run.set_sensitive(notis_loading)
-
-ifis_loading:
-self.loading.show()
-glib.timeout_add(500,self._make_progress_bar_go_crazy)
-else:
-self.loading.hide()
-
-def_on_result_ready(self,result):
-status,value=result
-self.set_loading(False)
-
-ifstatus:
-content=str(value)
-else:
-content="exception running function: %s"%str(value)
-
-self.text.get_buffer().set_text(content)
-
-def_make_progress_bar_go_crazy(self):
-ifself.is_loading:
-self.loading.pulse()
-
-returnself.is_loading
-
-gtk.gdk.threads_init()
-Display("load the content of website",load_site,
-"http://marianoguerra.com.ar").show()
-gtk.main()
-
-if__name__=='__main__':
-main()
+
'''example of a generic function to run a given function in a thread and call a
+callback in the main thread with the result of the function'''
+
+importgtk
+importglib
+importtime
+importQueue
+importurllib
+importthreading
+
+# this is the important function, copy this to your project to reuse it
+defrun_in_thread(callback,func,*args,**kwargs):
+'''run *func* in a thread with *args* and *kwargs* as arguments, when
+ finished call callback with a two item tuple containing a boolean as first
+ item informing if the function returned correctly and the returned value or
+ the exception thrown as second item
+ '''
+
+queue=Queue.Queue()
+
+defrun():
+'''
+ main function of the thread, run func with args and kwargs
+ and get the result, call callback with the (True, result)
+
+ if an exception is thrown call callback with (False, exception)
+ '''
+try:
+result=(True,func(*args,**kwargs))
+exceptException,ex:
+result=(False,ex)
+
+queue.put(result)
+
+defcheck():
+'''
+ check if func finished
+ '''
+try:
+result=queue.get(False,0.1)
+exceptQueue.Empty:
+returnTrue
+
+callback(result)
+returnFalse
+
+glib.timeout_add_seconds(1,check)
+thread=threading.Thread(target=run)
+thread.setDaemon(True)
+thread.start()
+
+# everything below is just for the demo
+defmain():
+'''
+ main function called when the module is run from the command line
+ '''
+
+defload_site(url):
+'''
+ a demo function that loads the content of a url
+ '''
+returnurllib.urlopen(url).read()
+
+classDisplay(gtk.Window):
+'''
+ a window to display some content that loads slowly
+ '''
+
+def__init__(self,text,func,*args,**kwargs):
+gtk.Window.__init__(self)
+self.set_default_size(400,300)
+self.set_title("display")
+self.set_border_width(2)
+
+self.func=func
+self.args=args
+self.kwargs=kwargs
+
+vbox=gtk.VBox(spacing=2)
+scroll=gtk.ScrolledWindow()
+self.text=gtk.TextView()
+self.text.get_buffer().set_text(text)
+
+scroll.add(self.text)
+
+vbox.pack_start(scroll,True,True)
+
+self.loading=gtk.ProgressBar()
+self.is_loading=False
+
+vbox.pack_start(self.loading,False)
+
+buttons=gtk.HButtonBox()
+self.run=gtk.Button(stock=gtk.STOCK_EXECUTE)
+self.run.connect('clicked',self._on_run_clicked)
+buttons.pack_start(self.run)
+
+vbox.pack_start(buttons,False)
+
+self.add(vbox)
+
+vbox.show_all()
+self.loading.hide()
+self.connect("delete-event",gtk.main_quit)
+
+def_on_run_clicked(self,button):
+self.set_loading()
+run_in_thread(self._on_result_ready,self.func,*self.args,
+**self.kwargs)
+
+defset_loading(self,is_loading=True):
+'''
+ set the window to the loading state
+ '''
+self.is_loading=is_loading
+self.run.set_sensitive(notis_loading)
+
+ifis_loading:
+self.loading.show()
+glib.timeout_add(500,self._make_progress_bar_go_crazy)
+else:
+self.loading.hide()
+
+def_on_result_ready(self,result):
+status,value=result
+self.set_loading(False)
+
+ifstatus:
+content=str(value)
+else:
+content="exception running function: %s"%str(value)
+
+self.text.get_buffer().set_text(content)
+
+def_make_progress_bar_go_crazy(self):
+ifself.is_loading:
+self.loading.pulse()
+
+returnself.is_loading
+
+gtk.gdk.threads_init()
+Display("load the content of website",load_site,
+"http://marianoguerra.com.ar").show()
+gtk.main()
+
+if__name__=='__main__':
+main()
diff --git a/recetario/gui/gtk/gladeholamundooo/index.html b/recetario/gui/gtk/gladeholamundooo/index.html
index ece4d86d6..8321691ab 100644
--- a/recetario/gui/gtk/gladeholamundooo/index.html
+++ b/recetario/gui/gtk/gladeholamundooo/index.html
@@ -27,7 +27,7 @@
gtk-glade-holamundo.glade
Copiar el co'>
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Ejemplo que carga la interfaz de un archivo .glade y lo muestra, el archivo .glade puede tener cualquier contenido mientras la ventana tenga el nombre "ventana"
gtk-glade-holamundo.glade
Copiar el contenido siguiente a un archivo llamado gtk-glade-holamundo.glade el archivo fue editado con glade-3.
-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--Generated with glade3 3.4.2 on Sat May 10 01:13:03 2008 -->
-<glade-interface>
-<widgetclass="GtkWindow"id="ventana">
-<propertyname="title"translatable="yes">holamundoglade</property>
-<propertyname="window_position">GTK_WIN_POS_CENTER</property>
-<propertyname="default_width">200</property>
-<propertyname="default_height">200</property>
-<signalname="delete_event"handler="on_ventana_delete_event"/>
-<child>
-<widgetclass="GtkLabel"id="label">
-<propertyname="visible">True</property>
-<propertyname="label"translatable="yes">holapyar!</property>
-</widget>
-</child>
-</widget>
-</glade-interface>
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.2 on Sat May 10 01:13:03 2008 -->
+<glade-interface>
+<widgetclass="GtkWindow"id="ventana">
+<propertyname="title"translatable="yes">holamundoglade</property>
+<propertyname="window_position">GTK_WIN_POS_CENTER</property>
+<propertyname="default_width">200</property>
+<propertyname="default_height">200</property>
+<signalname="delete_event"handler="on_ventana_delete_event"/>
+<child>
+<widgetclass="GtkLabel"id="label">
+<propertyname="visible">True</property>
+<propertyname="label"translatable="yes">holapyar!</property>
+</widget>
+</child>
+</widget>
+</glade-interface>
El código para el ejemplo es el siguiente:
-
importgtk
-importsys
-importgtk.glade
-
-classHolaMundo(object):
-'''clase que muestra un hola mundo desde un archivo glade'''
-
-def__init__(self):
-'''constructor'''
-self.tree=gtk.glade.XML("gtk-glade-holamundo.glade")
-self.tree.signal_autoconnect(self)
-self.window=self.tree.get_widget("ventana")
-
-defon_ventana_delete_event(self,window,event):
-'''callback llamado cuando se cierra la ventana'''
-sys.exit(0)
-
-defshow(self):
-'''muestra la ventana principal'''
-self.window.show_all()
-
-if__name__=="__main__":
-hola=HolaMundo()
-hola.show()
-gtk.main()
+
importgtk
+importsys
+importgtk.glade
+
+classHolaMundo(object):
+'''clase que muestra un hola mundo desde un archivo glade'''
+
+def__init__(self):
+'''constructor'''
+self.tree=gtk.glade.XML("gtk-glade-holamundo.glade")
+self.tree.signal_autoconnect(self)
+self.window=self.tree.get_widget("ventana")
+
+defon_ventana_delete_event(self,window,event):
+'''callback llamado cuando se cierra la ventana'''
+sys.exit(0)
+
+defshow(self):
+'''muestra la ventana principal'''
+self.window.show_all()
+
+if__name__=="__main__":
+hola=HolaMundo()
+hola.show()
+gtk.main()
diff --git a/recetario/gui/gtk/grid/index.html b/recetario/gui/gtk/grid/index.html
index 2a7c6b8ca..08b536354 100644
--- a/recetario/gui/gtk/grid/index.html
+++ b/recetario/gui/gtk/grid/index.html
@@ -24,7 +24,7 @@
-
+
Ir al contenido principal
@@ -58,12 +58,12 @@
diff --git a/recetario/gui/gtk/hbox/index.html b/recetario/gui/gtk/hbox/index.html
index d92120367..dfb989660 100644
--- a/recetario/gui/gtk/hbox/index.html
+++ b/recetario/gui/gtk/hbox/index.html
@@ -30,7 +30,7 @@
class Ventana(gtk.Window):
'''clase que define una ventana que saluda'''">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
Ejemplo que muestra el uso de hbox (cajas horizontales) para ordenar elementos de forma horizontal.
-
importgtk
-importsys
-
-classVentana(gtk.Window):
-'''clase que define una ventana que saluda'''
-
-def__init__(self):
-'''constructor, se llama al constructor de la clase padre'''
-gtk.Window.__init__(self)
-
-self.set_default_size(200,200)
-self.set_title("hbox")
-# creamos una caja horizontal que contiene elementos
-# de manera horizontal
-self.hbox=gtk.HBox()
-# agregamos tres elementos
-self.hbox.pack_start(gtk.Label("uno"))
-self.hbox.pack_start(gtk.Label("dos"))
-self.hbox.pack_start(gtk.Label("tres"))
-
-self.add(self.hbox)
-self.hbox.show_all()
-
-self.connect("delete-event",self.on_delete)
-
-defon_delete(self,window,event):
-'''llamado cuando se cierra la ventana'''
-sys.exit(0)
-
-if__name__=="__main__":
-ventana=Ventana()
-ventana.show()
-gtk.main()
+
importgtk
+importsys
+
+classVentana(gtk.Window):
+'''clase que define una ventana que saluda'''
+
+def__init__(self):
+'''constructor, se llama al constructor de la clase padre'''
+gtk.Window.__init__(self)
+
+self.set_default_size(200,200)
+self.set_title("hbox")
+# creamos una caja horizontal que contiene elementos
+# de manera horizontal
+self.hbox=gtk.HBox()
+# agregamos tres elementos
+self.hbox.pack_start(gtk.Label("uno"))
+self.hbox.pack_start(gtk.Label("dos"))
+self.hbox.pack_start(gtk.Label("tres"))
+
+self.add(self.hbox)
+self.hbox.show_all()
+
+self.connect("delete-event",self.on_delete)
+
+defon_delete(self,window,event):
+'''llamado cuando se cierra la ventana'''
+sys.exit(0)
+
+if__name__=="__main__":
+ventana=Ventana()
+ventana.show()
+gtk.main()
diff --git a/recetario/gui/gtk/holamundo/index.html b/recetario/gui/gtk/holamundo/index.html
index 655c5c807..e069c5229 100644
--- a/recetario/gui/gtk/holamundo/index.html
+++ b/recetario/gui/gtk/holamundo/index.html
@@ -32,7 +32,7 @@
# seteamos el tamanio de la ventana
window.set_default_size(200,">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
Crea y muestra una ventana que muestra el famoso mensaje hola mundo.
-
importgtk
-importsys
-
-# se crea la ventana
-window=gtk.Window()
-# seteamos el tamanio de la ventana
-window.set_default_size(200,200)
-# se crea la etiqueta que va a mostrar el mensaje
-label=gtk.Label("Hola pyar!")
-# se setea el el titulo de la ventana
-window.set_title("hola mundo")
-# agregamos el label a la ventana
-window.add(label)
-# mostramos la ventana y todo lo que contiene
-window.show_all()
-
-defon_window_close(window,event):
-'''este metodo es llamado cuando se aprieta la equis para cerrar la
- ventana'''
-# cerramos el programa retornando 0 (exito)
-sys.exit(0)
-
-# conectamos la senial delete-event que es emitida cuando se presiona la
-# equis en la ventana
-window.connect("delete-event",on_window_close)
-
-# llamamos al main loop para que muestre la ventana y
-# procese los eventos
-gtk.main()
+
importgtk
+importsys
+
+# se crea la ventana
+window=gtk.Window()
+# seteamos el tamanio de la ventana
+window.set_default_size(200,200)
+# se crea la etiqueta que va a mostrar el mensaje
+label=gtk.Label("Hola pyar!")
+# se setea el el titulo de la ventana
+window.set_title("hola mundo")
+# agregamos el label a la ventana
+window.add(label)
+# mostramos la ventana y todo lo que contiene
+window.show_all()
+
+defon_window_close(window,event):
+'''este metodo es llamado cuando se aprieta la equis para cerrar la
+ ventana'''
+# cerramos el programa retornando 0 (exito)
+sys.exit(0)
+
+# conectamos la senial delete-event que es emitida cuando se presiona la
+# equis en la ventana
+window.connect("delete-event",on_window_close)
+
+# llamamos al main loop para que muestre la ventana y
+# procese los eventos
+gtk.main()
diff --git a/recetario/gui/gtk/holamundooo/index.html b/recetario/gui/gtk/holamundooo/index.html
index f19f8c6ef..3e1cb5637 100644
--- a/recetario/gui/gtk/holamundooo/index.html
+++ b/recetario/gui/gtk/holamundooo/index.html
@@ -33,7 +33,7 @@
def __init__(self):
">
-
+
Ir al contenido principal
@@ -67,12 +67,12 @@
Ejemplo que hace lo mismo que GtkHolaMundo pero orientado a objetos.
-
importgtk
-importsys
-
-classHolaMundo(gtk.Window):
-'''clase que define una ventana que saluda'''
-
-def__init__(self):
-'''constructor, se llama al constructor de la clase padre'''
-gtk.Window.__init__(self)
-
-self.set_default_size(200,200)
-self.label=gtk.Label("Hola pyar")
-self.set_title("hola mundo oo")
-self.add(self.label)
-self.label.show()
-
-self.connect("delete-event",self.on_delete)
-
-defon_delete(self,window,event):
-'''llamado cuando se cierra la ventana'''
-sys.exit(0)
-
-if__name__=="__main__":
-hola=HolaMundo()
-hola.show()
-gtk.main()
+
importgtk
+importsys
+
+classHolaMundo(gtk.Window):
+'''clase que define una ventana que saluda'''
+
+def__init__(self):
+'''constructor, se llama al constructor de la clase padre'''
+gtk.Window.__init__(self)
+
+self.set_default_size(200,200)
+self.label=gtk.Label("Hola pyar")
+self.set_title("hola mundo oo")
+self.add(self.label)
+self.label.show()
+
+self.connect("delete-event",self.on_delete)
+
+defon_delete(self,window,event):
+'''llamado cuando se cierra la ventana'''
+sys.exit(0)
+
+if__name__=="__main__":
+hola=HolaMundo()
+hola.show()
+gtk.main()
diff --git a/recetario/gui/gtk/labelconcolor/index.html b/recetario/gui/gtk/labelconcolor/index.html
index 37116f9ca..a044a5899 100644
--- a/recetario/gui/gtk/labelconcolor/index.html
+++ b/recetario/gui/gtk/labelconcolor/index.html
@@ -28,7 +28,7 @@
window = ">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
importgtk
-importgobject
-
-classGtkListExample(gtk.Window):
-'''clase que representa una ventana con una lista'''
-
-def__init__(self,width=640,height=480,title="gtk list example",
-on_exit=gtk.main_quit):
-'''constructor'''
-# llamamos al constructor de la clase padre
-gtk.Window.__init__(self)
-
-# establecemos el tamanio
-self.set_default_size(width,height)
-# establecemos el titulo
-self.set_title(title)
-
-# creamos el modelo de cada fila
-# el modelo y la vista se crean separadamente y se relacionan despues
-# https://es.wikipedia.org/wiki/Modelo_Vista_Controlador
-self.model=gtk.ListStore(str,int,bool)
-# creamos el widget que va a mostrar la lista y le pasamos el modelo
-self.list=gtk.TreeView(self.model)
-
-# creamos los objetos que van a renderizar los atributos
-textrenderer=gtk.CellRendererText()
-# seteamos una propiedad
-textrenderer.set_property("xalign",0.5)
-# un renderer para renderizar booleanos como checkbox
-boolrenderer=gtk.CellRendererToggle()
-
-# creamos las columnas de la lista
-# no necesariamente todos los elementos del modelo se deben mostrar
-# tampoco es necesario que se muestren en el orden del modelo, por
-# eso creamos las columnas para decirle que elementos del modelo
-# mostrar y como mostrarlos
-column1=gtk.TreeViewColumn("nombre",textrenderer,text=0)
-column1.set_expand(True)
-
-column2=gtk.TreeViewColumn("edad",textrenderer,text=1)
-column2.set_expand(True)
-
-column3=gtk.TreeViewColumn("algo",boolrenderer,active=2)
-column3.set_expand(True)
-
-# agregamos las columnas
-self.list.append_column(column1)
-self.list.append_column(column2)
-self.list.append_column(column3)
-
-# agregamos la lista a la ventana
-self.add(self.list)
-# mostramos el widget
-self.list.show_all()
-# conectamos un manejador para cuando aprieten cerrar
-self.connect('delete-event',on_exit)
-
-defadd_item(self,string,number,boolean):
-# agregamos una fila al modelo
-self.model.append((string,number,boolean))
-
-if__name__=="__main__":
-window=GtkListExample()
-window.show()
-window.add_item("bob",26,True)
-window.add_item("patricio",24,True)
-window.add_item("arenita",27,False)
-
-gtk.main()
+
importgtk
+importgobject
+
+classGtkListExample(gtk.Window):
+'''clase que representa una ventana con una lista'''
+
+def__init__(self,width=640,height=480,title="gtk list example",
+on_exit=gtk.main_quit):
+'''constructor'''
+# llamamos al constructor de la clase padre
+gtk.Window.__init__(self)
+
+# establecemos el tamanio
+self.set_default_size(width,height)
+# establecemos el titulo
+self.set_title(title)
+
+# creamos el modelo de cada fila
+# el modelo y la vista se crean separadamente y se relacionan despues
+# https://es.wikipedia.org/wiki/Modelo_Vista_Controlador
+self.model=gtk.ListStore(str,int,bool)
+# creamos el widget que va a mostrar la lista y le pasamos el modelo
+self.list=gtk.TreeView(self.model)
+
+# creamos los objetos que van a renderizar los atributos
+textrenderer=gtk.CellRendererText()
+# seteamos una propiedad
+textrenderer.set_property("xalign",0.5)
+# un renderer para renderizar booleanos como checkbox
+boolrenderer=gtk.CellRendererToggle()
+
+# creamos las columnas de la lista
+# no necesariamente todos los elementos del modelo se deben mostrar
+# tampoco es necesario que se muestren en el orden del modelo, por
+# eso creamos las columnas para decirle que elementos del modelo
+# mostrar y como mostrarlos
+column1=gtk.TreeViewColumn("nombre",textrenderer,text=0)
+column1.set_expand(True)
+
+column2=gtk.TreeViewColumn("edad",textrenderer,text=1)
+column2.set_expand(True)
+
+column3=gtk.TreeViewColumn("algo",boolrenderer,active=2)
+column3.set_expand(True)
+
+# agregamos las columnas
+self.list.append_column(column1)
+self.list.append_column(column2)
+self.list.append_column(column3)
+
+# agregamos la lista a la ventana
+self.add(self.list)
+# mostramos el widget
+self.list.show_all()
+# conectamos un manejador para cuando aprieten cerrar
+self.connect('delete-event',on_exit)
+
+defadd_item(self,string,number,boolean):
+# agregamos una fila al modelo
+self.model.append((string,number,boolean))
+
+if__name__=="__main__":
+window=GtkListExample()
+window.show()
+window.add_item("bob",26,True)
+window.add_item("patricio",24,True)
+window.add_item("arenita",27,False)
+
+gtk.main()
diff --git a/recetario/gui/gtk/menu/index.html b/recetario/gui/gtk/menu/index.html
index 0dc810a2f..31b8bc9ce 100644
--- a/recetario/gui/gtk/menu/index.html
+++ b/recetario/gui/gtk/menu/index.html
@@ -24,7 +24,7 @@
-
+
Ir al contenido principal
@@ -58,12 +58,12 @@
Ejemplo de cómo manipular la api desde múltiples threads sin usar locks. Compare con el otro ejemplo que no utiliza colas.
-
importgtk
-importtime
-importQueue
-importrandom
-importgobject
-importthreading
-
-TEXTS=['eggs','spam','pyar','gtk']
-
-classMolesto(threading.Thread):
-'''un thread que quiere molestar el main thread'''
-
-def__init__(self,label,cola):
-threading.Thread.__init__(self)
-self.setDaemon(True)
-self.label=label# no usar en este thread!
-self.cola=cola
-
-defrun(self):
-'''metodo principal del thread, duerme un tiempo aleatorio y despues
- pone algo en la cola para que el main thread lo haga'''
-
-whileTrue:
-time.sleep(random.random()*5)
-texto=self.getName()+' '+random.choice(TEXTS)
-printself.getName(),'escribiendo',texto
-self.cola.put((self.label.set_text,(texto,),{}))
-
-classVentana(gtk.Window):
-'''ventana con un label, ninguna locura'''
-
-def__init__(self):
-gtk.Window.__init__(self)
-self.set_default_size(640,480)
-self.set_title('gtk con threads')
-self.label=gtk.Label('')
-self.add(self.label)
-self.label.show()
-
-
-queue=Queue.Queue()
-defqueue_manager():
-try:
-whileTrue:
-method,args,kwargs=queue.get(True,0.1)
-print'ejecutando',method.__name__,'con',args,kwargs
-method(*args,**kwargs)
-exceptQueue.Empty:
-pass
-
-returnTrue
-
-if__name__=='__main__':
-gtk.gdk.threads_init()
-gobject.timeout_add(200,queue_manager)
-ventana=Ventana()
-ventana.show()
-threads=[Molesto(ventana.label,queue)forxinrange(10)]
-forthreadinthreads:
-thread.start()
-gtk.main()
+
importgtk
+importtime
+importQueue
+importrandom
+importgobject
+importthreading
+
+TEXTS=['eggs','spam','pyar','gtk']
+
+classMolesto(threading.Thread):
+'''un thread que quiere molestar el main thread'''
+
+def__init__(self,label,cola):
+threading.Thread.__init__(self)
+self.setDaemon(True)
+self.label=label# no usar en este thread!
+self.cola=cola
+
+defrun(self):
+'''metodo principal del thread, duerme un tiempo aleatorio y despues
+ pone algo en la cola para que el main thread lo haga'''
+
+whileTrue:
+time.sleep(random.random()*5)
+texto=self.getName()+' '+random.choice(TEXTS)
+printself.getName(),'escribiendo',texto
+self.cola.put((self.label.set_text,(texto,),{}))
+
+classVentana(gtk.Window):
+'''ventana con un label, ninguna locura'''
+
+def__init__(self):
+gtk.Window.__init__(self)
+self.set_default_size(640,480)
+self.set_title('gtk con threads')
+self.label=gtk.Label('')
+self.add(self.label)
+self.label.show()
+
+
+queue=Queue.Queue()
+defqueue_manager():
+try:
+whileTrue:
+method,args,kwargs=queue.get(True,0.1)
+print'ejecutando',method.__name__,'con',args,kwargs
+method(*args,**kwargs)
+exceptQueue.Empty:
+pass
+
+returnTrue
+
+if__name__=='__main__':
+gtk.gdk.threads_init()
+gobject.timeout_add(200,queue_manager)
+ventana=Ventana()
+ventana.show()
+threads=[Molesto(ventana.label,queue)forxinrange(10)]
+forthreadinthreads:
+thread.start()
+gtk.main()
diff --git a/recetario/gui/gtk/multithread2/index.html b/recetario/gui/gtk/multithread2/index.html
index 3ec5d4936..f7612e234 100644
--- a/recetario/gui/gtk/multithread2/index.html
+++ b/recetario/gui/gtk/multithread2/index.html
@@ -35,7 +35,7 @@
">
-
+
Ir al contenido principal
@@ -69,12 +69,12 @@
Este ejemplo muestra como usar gtk para mostrar el diálogo de imprimir pero sin usar el main loop.
Es útil para aplicaciones no gtk que solo quieren usar el diálogo de impresión pero tienen otro main loop que no es el de gtk.
Explicación: Lo que hacemos después de mostrar el diálogo es procesar los eventos de gtk mientras haya eventos pendientes, luego seguimos en nuestra aplicación normalmente.
Ejemplo sobre cómo mostrar texto con formato en un gtk.TextView, se crea una clase que extiende gtk.TextBuffer para facilitar la inserción de texto con formato.
-
'''a module that contains a class to insert rich text into a textview'''
-
-importgtk
-importpango
-
-classRichBuffer(gtk.TextBuffer):
-'''a buffer that makes it easy to manipulate a gtk textview with
- rich text'''
-
-def__init__(self):
-'''constructor'''
-gtk.TextBuffer.__init__(self)
-
-self.colormap=gtk.gdk.colormap_get_system()
-
-self.fg_tags={}
-self.bg_tags={}
-self.font_tags={}
-self.size_tags={}
-self.bold_tag=self.create_tag("bold",weight=pango.WEIGHT_BOLD)
-self.italic_tag=self.create_tag("italic",style=pango.STYLE_ITALIC)
-self.underline_tag=self.create_tag("underline",
-underline=pango.UNDERLINE_SINGLE)
-self.strike_tag=self.create_tag("strike",strikethrough=True)
-
-defput_text(self,text,fg_color=None,bg_color=None,font=None,size=None,
-bold=False,italic=False,underline=False,strike=False):
-'''insert text at the current position with the style defined by the
- optional parameters'''
-tags=self._parse_tags(fg_color,bg_color,font,size,bold,italic,
-underline,strike)
-iterator=self.get_iter_at_mark(self.get_insert())
-self._insert(iterator,text,tags)
-
-def_insert(self,iterator,text,tags=None):
-'''insert text at the current position with the style defined by the
- optional parameters'''
-iftagsisnotNone:
-self.insert_with_tags(iterator,text,*tags)
-else:
-self.insert(iterator,text)
-
-def_parse_tags(self,fg_color=None,bg_color=None,font=None,size=None,
-bold=False,italic=False,underline=False,strike=False):
-'''parse the parameters and return a list of tags to apply that
- format
- '''
-tags=[]
-
-iffg_color:
-tag=self._parse_fg(fg_color)
-iftag:
-tags.append(tag)
-
-ifbg_color:
-tag=self._parse_bg(bg_color)
-iftag:
-tags.append(tag)
-
-iffont:
-tag=self._parse_font(font)
-iftag:
-tags.append(tag)
-
-ifsize:
-tag=self._parse_size(size)
-iftag:
-tags.append(tag)
-
-ifbold:
-tags.append(self.bold_tag)
-
-ifitalic:
-tags.append(self.italic_tag)
-
-ifunderline:
-tags.append(self.underline_tag)
-
-ifstrike:
-tags.append(self.strike_tag)
-
-returntags
-
-def_parse_fg(self,value):
-'''parse the foreground color and return a tag'''
-ifvalueinself.fg_tags:
-returnself.fg_tags[value]
-
-try:
-color=gtk.gdk.color_parse(value)
-self.colormap.alloc_color(color)
-exceptValueError:
-returnNone
-
-color_tag=self.create_tag('fg_'+value[1:],foreground_gdk=color)
-self.fg_tags[value]=color_tag
-
-returncolor_tag
-
-def_parse_bg(self,value):
-'''parse the background color and return a tag'''
-ifvalueinself.bg_tags:
-returnself.bg_tags[value]
-
-try:
-color=gtk.gdk.color_parse(value)
-self.colormap.alloc_color(color)
-exceptValueError:
-returnNone
-
-color_tag=self.create_tag('bg_'+value[1:],background_gdk=color)
-self.bg_tags[value]=color_tag
-
-returncolor_tag
-
-def_parse_font(self,value):
-'''parse the font and return a tag'''
-ifvalueinself.font_tags:
-returnself.font_tags[value]
-
-font_tag=self.create_tag('font_'+value.replace(' ','_'),
-font=value)
-self.font_tags[value]=font_tag
-
-returnfont_tag
-
-def_parse_size(self,value):
-'''parse the font size and return a tag'''
-ifvalueinself.size_tags:
-returnself.size_tags[value]
-
-size_tag=self.create_tag('size_'+str(value),size_points=value)
-self.size_tags[value]=size_tag
-returnsize_tag
-
-deftest():
-'''do some tests with the buffer'''
-importsys
-defon_close(widget,event):
-'''method called when the window is closed'''
-sys.exit(0)
-
-window=gtk.Window()
-window.set_default_size(640,480)
-window.connect('delete-event',on_close)
-textview=gtk.TextView()
-buff=RichBuffer()
-textview.set_buffer(buff)
-window.add(textview)
-window.show_all()
-buff.put_text('buenas, como va? ','#CCCCCC','#000000','Arial',12)
-buff.put_text('esto es una prueba\n','#CC0000','#AAAAAA','Purisa',14)
-buff.put_text('un poco de formato\n','#00CC00','#FFFFFF','Andale Mono',
-8,True,True,True,True)
-buff.put_text('un poco mas\n','#CCCCCC','#0000CC','Andale Mono',16,
-False,True,False,True)
-gtk.main()
-
-if__name__=='__main__':
-test()
+
'''a module that contains a class to insert rich text into a textview'''
+
+importgtk
+importpango
+
+classRichBuffer(gtk.TextBuffer):
+'''a buffer that makes it easy to manipulate a gtk textview with
+ rich text'''
+
+def__init__(self):
+'''constructor'''
+gtk.TextBuffer.__init__(self)
+
+self.colormap=gtk.gdk.colormap_get_system()
+
+self.fg_tags={}
+self.bg_tags={}
+self.font_tags={}
+self.size_tags={}
+self.bold_tag=self.create_tag("bold",weight=pango.WEIGHT_BOLD)
+self.italic_tag=self.create_tag("italic",style=pango.STYLE_ITALIC)
+self.underline_tag=self.create_tag("underline",
+underline=pango.UNDERLINE_SINGLE)
+self.strike_tag=self.create_tag("strike",strikethrough=True)
+
+defput_text(self,text,fg_color=None,bg_color=None,font=None,size=None,
+bold=False,italic=False,underline=False,strike=False):
+'''insert text at the current position with the style defined by the
+ optional parameters'''
+tags=self._parse_tags(fg_color,bg_color,font,size,bold,italic,
+underline,strike)
+iterator=self.get_iter_at_mark(self.get_insert())
+self._insert(iterator,text,tags)
+
+def_insert(self,iterator,text,tags=None):
+'''insert text at the current position with the style defined by the
+ optional parameters'''
+iftagsisnotNone:
+self.insert_with_tags(iterator,text,*tags)
+else:
+self.insert(iterator,text)
+
+def_parse_tags(self,fg_color=None,bg_color=None,font=None,size=None,
+bold=False,italic=False,underline=False,strike=False):
+'''parse the parameters and return a list of tags to apply that
+ format
+ '''
+tags=[]
+
+iffg_color:
+tag=self._parse_fg(fg_color)
+iftag:
+tags.append(tag)
+
+ifbg_color:
+tag=self._parse_bg(bg_color)
+iftag:
+tags.append(tag)
+
+iffont:
+tag=self._parse_font(font)
+iftag:
+tags.append(tag)
+
+ifsize:
+tag=self._parse_size(size)
+iftag:
+tags.append(tag)
+
+ifbold:
+tags.append(self.bold_tag)
+
+ifitalic:
+tags.append(self.italic_tag)
+
+ifunderline:
+tags.append(self.underline_tag)
+
+ifstrike:
+tags.append(self.strike_tag)
+
+returntags
+
+def_parse_fg(self,value):
+'''parse the foreground color and return a tag'''
+ifvalueinself.fg_tags:
+returnself.fg_tags[value]
+
+try:
+color=gtk.gdk.color_parse(value)
+self.colormap.alloc_color(color)
+exceptValueError:
+returnNone
+
+color_tag=self.create_tag('fg_'+value[1:],foreground_gdk=color)
+self.fg_tags[value]=color_tag
+
+returncolor_tag
+
+def_parse_bg(self,value):
+'''parse the background color and return a tag'''
+ifvalueinself.bg_tags:
+returnself.bg_tags[value]
+
+try:
+color=gtk.gdk.color_parse(value)
+self.colormap.alloc_color(color)
+exceptValueError:
+returnNone
+
+color_tag=self.create_tag('bg_'+value[1:],background_gdk=color)
+self.bg_tags[value]=color_tag
+
+returncolor_tag
+
+def_parse_font(self,value):
+'''parse the font and return a tag'''
+ifvalueinself.font_tags:
+returnself.font_tags[value]
+
+font_tag=self.create_tag('font_'+value.replace(' ','_'),
+font=value)
+self.font_tags[value]=font_tag
+
+returnfont_tag
+
+def_parse_size(self,value):
+'''parse the font size and return a tag'''
+ifvalueinself.size_tags:
+returnself.size_tags[value]
+
+size_tag=self.create_tag('size_'+str(value),size_points=value)
+self.size_tags[value]=size_tag
+returnsize_tag
+
+deftest():
+'''do some tests with the buffer'''
+importsys
+defon_close(widget,event):
+'''method called when the window is closed'''
+sys.exit(0)
+
+window=gtk.Window()
+window.set_default_size(640,480)
+window.connect('delete-event',on_close)
+textview=gtk.TextView()
+buff=RichBuffer()
+textview.set_buffer(buff)
+window.add(textview)
+window.show_all()
+buff.put_text('buenas, como va? ','#CCCCCC','#000000','Arial',12)
+buff.put_text('esto es una prueba\n','#CC0000','#AAAAAA','Purisa',14)
+buff.put_text('un poco de formato\n','#00CC00','#FFFFFF','Andale Mono',
+8,True,True,True,True)
+buff.put_text('un poco mas\n','#CCCCCC','#0000CC','Andale Mono',16,
+False,True,False,True)
+gtk.main()
+
+if__name__=='__main__':
+test()
Más información:
diff --git a/recetario/gui/gtk/runner/index.html b/recetario/gui/gtk/runner/index.html
index fa0373b03..8f1336415 100644
--- a/recetario/gui/gtk/runner/index.html
+++ b/recetario/gui/gtk/runner/index.html
@@ -28,7 +28,7 @@
callback f">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
func(*args, **kwargs) será llamada en un thread aparte el cuál será monitoreado periódicamente por su finalizacion. Una vez terminado llamará a callback pasándole una tupla cuyo primer elemento es True sí la función terminó con éxito y False sí la función lanzó una excepción. El segundo elemento de la tupla es el valor retornado por la función sí tuvo éxito o la excepción lanzada en caso que haya fallado.
Obviamente en la función esa no pueden correr código relacionado con gtk.
-
'''example of a generic class to run a given function in a thread and call a
-callback in the main thread with the result of the function'''
-
-importgtk
-importglib
-importtime
-importQueue
-importurllib
-importthreading
-
-classGtkRunner(threading.Thread):
-'''run *func* in a thread with *args* and *kwargs* as arguments, when
- finished call callback with a two item tuple containing a boolean as first
- item informing if the function returned correctly and the returned value or
- the exception thrown as second item
- '''
-
-def__init__(self,callback,func,*args,**kwargs):
-threading.Thread.__init__(self)
-self.setDaemon(True)
-
-self.callback=callback
-self.func=func
-self.args=args
-self.kwargs=kwargs
-
-self.result=Queue.Queue()
-
-self.start()
-glib.timeout_add_seconds(1,self.check)
-
-defrun(self):
-'''
- main function of the thread, run func with args and kwargs
- and get the result, call callback with the (True, result)
-
- if an exception is thrown call callback with (False, exception)
- '''
-try:
-result=(True,self.func(*self.args,**self.kwargs))
-exceptException,ex:
-result=(False,ex)
-
-self.result.put(result)
-
-defcheck(self):
-'''
- check if func finished
- '''
-try:
-result=self.result.get(False,0.1)
-exceptQueue.Empty:
-returnTrue
-
-self.callback(result)
-returnFalse
-
-
-defmain():
-'''
- main function called when the module is run from the command line
- '''
-
-defreturn_slow(result,sleep=5):
-'''
- a demo function that returns result slowly
- '''
-time.sleep(sleep)
-returnresult
-
-deffail_slow(message,sleep=5):
-'''
- a demo function that raises an exception slowly
- '''
-time.sleep(sleep)
-raiseException(message)
-
-defload_site(url):
-'''
- a demo function that loads the content of a url
- '''
-returnurllib.urlopen(url).read()
-
-classDisplay(gtk.Window):
-'''
- a window to display some content that loads slowly
- '''
-
-def__init__(self,text,func,*args,**kwargs):
-gtk.Window.__init__(self)
-self.set_default_size(400,300)
-self.set_title("display")
-self.set_border_width(2)
-
-self.func=func
-self.args=args
-self.kwargs=kwargs
-
-vbox=gtk.VBox(spacing=2)
-scroll=gtk.ScrolledWindow()
-self.text=gtk.TextView()
-self.text.get_buffer().set_text(text)
-
-scroll.add(self.text)
-
-vbox.pack_start(scroll,True,True)
-
-self.loading=gtk.ProgressBar()
-self.is_loading=False
-
-vbox.pack_start(self.loading,False)
-
-buttons=gtk.HButtonBox()
-self.run=gtk.Button(stock=gtk.STOCK_EXECUTE)
-self.run.connect('clicked',self._on_run_clicked)
-buttons.pack_start(self.run)
-
-vbox.pack_start(buttons,False)
-
-self.add(vbox)
-
-vbox.show_all()
-self.loading.hide()
-self.connect("delete-event",gtk.main_quit)
-
-def_on_run_clicked(self,button):
-self.set_loading()
-GtkRunner(self._on_result_ready,self.func,*self.args,
-**self.kwargs)
-
-defset_loading(self,is_loading=True):
-'''
- set the window to the loading state
- '''
-self.is_loading=is_loading
-self.run.set_sensitive(notis_loading)
-
-ifis_loading:
-self.loading.show()
-glib.timeout_add(500,self._make_progress_bar_go_crazy)
-else:
-self.loading.hide()
-
-def_on_result_ready(self,result):
-status,value=result
-self.set_loading(False)
-
-ifstatus:
-content=str(value)
-else:
-content="exception running function: %s"%str(value)
-
-self.text.get_buffer().set_text(content)
-
-def_make_progress_bar_go_crazy(self):
-ifself.is_loading:
-self.loading.pulse()
-
-returnself.is_loading
-
-gtk.gdk.threads_init()
-Display("show text after some seconds",return_slow,"I load slowly").show()
-Display("raise an exception after some seconds",fail_slow,
-"I fail slowly").show()
-Display("load the content of website",load_site,
-"http://marianoguerra.com.ar").show()
-gtk.main()
-
-if__name__=='__main__':
-main()
+
'''example of a generic class to run a given function in a thread and call a
+callback in the main thread with the result of the function'''
+
+importgtk
+importglib
+importtime
+importQueue
+importurllib
+importthreading
+
+classGtkRunner(threading.Thread):
+'''run *func* in a thread with *args* and *kwargs* as arguments, when
+ finished call callback with a two item tuple containing a boolean as first
+ item informing if the function returned correctly and the returned value or
+ the exception thrown as second item
+ '''
+
+def__init__(self,callback,func,*args,**kwargs):
+threading.Thread.__init__(self)
+self.setDaemon(True)
+
+self.callback=callback
+self.func=func
+self.args=args
+self.kwargs=kwargs
+
+self.result=Queue.Queue()
+
+self.start()
+glib.timeout_add_seconds(1,self.check)
+
+defrun(self):
+'''
+ main function of the thread, run func with args and kwargs
+ and get the result, call callback with the (True, result)
+
+ if an exception is thrown call callback with (False, exception)
+ '''
+try:
+result=(True,self.func(*self.args,**self.kwargs))
+exceptException,ex:
+result=(False,ex)
+
+self.result.put(result)
+
+defcheck(self):
+'''
+ check if func finished
+ '''
+try:
+result=self.result.get(False,0.1)
+exceptQueue.Empty:
+returnTrue
+
+self.callback(result)
+returnFalse
+
+
+defmain():
+'''
+ main function called when the module is run from the command line
+ '''
+
+defreturn_slow(result,sleep=5):
+'''
+ a demo function that returns result slowly
+ '''
+time.sleep(sleep)
+returnresult
+
+deffail_slow(message,sleep=5):
+'''
+ a demo function that raises an exception slowly
+ '''
+time.sleep(sleep)
+raiseException(message)
+
+defload_site(url):
+'''
+ a demo function that loads the content of a url
+ '''
+returnurllib.urlopen(url).read()
+
+classDisplay(gtk.Window):
+'''
+ a window to display some content that loads slowly
+ '''
+
+def__init__(self,text,func,*args,**kwargs):
+gtk.Window.__init__(self)
+self.set_default_size(400,300)
+self.set_title("display")
+self.set_border_width(2)
+
+self.func=func
+self.args=args
+self.kwargs=kwargs
+
+vbox=gtk.VBox(spacing=2)
+scroll=gtk.ScrolledWindow()
+self.text=gtk.TextView()
+self.text.get_buffer().set_text(text)
+
+scroll.add(self.text)
+
+vbox.pack_start(scroll,True,True)
+
+self.loading=gtk.ProgressBar()
+self.is_loading=False
+
+vbox.pack_start(self.loading,False)
+
+buttons=gtk.HButtonBox()
+self.run=gtk.Button(stock=gtk.STOCK_EXECUTE)
+self.run.connect('clicked',self._on_run_clicked)
+buttons.pack_start(self.run)
+
+vbox.pack_start(buttons,False)
+
+self.add(vbox)
+
+vbox.show_all()
+self.loading.hide()
+self.connect("delete-event",gtk.main_quit)
+
+def_on_run_clicked(self,button):
+self.set_loading()
+GtkRunner(self._on_result_ready,self.func,*self.args,
+**self.kwargs)
+
+defset_loading(self,is_loading=True):
+'''
+ set the window to the loading state
+ '''
+self.is_loading=is_loading
+self.run.set_sensitive(notis_loading)
+
+ifis_loading:
+self.loading.show()
+glib.timeout_add(500,self._make_progress_bar_go_crazy)
+else:
+self.loading.hide()
+
+def_on_result_ready(self,result):
+status,value=result
+self.set_loading(False)
+
+ifstatus:
+content=str(value)
+else:
+content="exception running function: %s"%str(value)
+
+self.text.get_buffer().set_text(content)
+
+def_make_progress_bar_go_crazy(self):
+ifself.is_loading:
+self.loading.pulse()
+
+returnself.is_loading
+
+gtk.gdk.threads_init()
+Display("show text after some seconds",return_slow,"I load slowly").show()
+Display("raise an exception after some seconds",fail_slow,
+"I fail slowly").show()
+Display("load the content of website",load_site,
+"http://marianoguerra.com.ar").show()
+gtk.main()
+
+if__name__=='__main__':
+main()
diff --git a/recetario/gui/gtk/statusicon/index.html b/recetario/gui/gtk/statusicon/index.html
index 72b24011c..f0257e691 100644
--- a/recetario/gui/gtk/statusicon/index.html
+++ b/recetario/gui/gtk/statusicon/index.html
@@ -31,7 +31,7 @@
class Tr">
-
+
Ir al contenido principal
@@ -65,12 +65,12 @@
Ejemplo que muestra todos los íconos stock de gtk con su respectivo nombre.
Un screenshot:
-
'''modulo que muestra el uso de los stock icons en gtk'''
-importgtk
-
-defrun():
-'''muestra una ventana con algunos elementos con stock icons'''
-ventana=gtk.Window()
-ventana.set_default_size(400,400)
-
-box=gtk.VBox(spacing=4)
-
-foridingtk.stock_list_ids():
-imagen=gtk.Image()
-imagen.set_from_stock(id,gtk.ICON_SIZE_BUTTON)
-
-etiqueta=gtk.Label("gtk.STOCK"+id[3:].replace("-","_").upper())
-etiqueta.set_alignment(0.0,0.5)
-
-caja=gtk.HBox()
-
-caja.pack_start(imagen,False)
-caja.pack_start(etiqueta)
-
-box.pack_start(caja)
-
-scroll=gtk.ScrolledWindow()
-scroll.add_with_viewport(box)
-scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
-
-ventana.add(scroll)
-
-ventana.connect('delete-event',gtk.main_quit)
-ventana.show_all()
-gtk.main()
-
-
-if__name__=='__main__':
-run()
+
'''modulo que muestra el uso de los stock icons en gtk'''
+importgtk
+
+defrun():
+'''muestra una ventana con algunos elementos con stock icons'''
+ventana=gtk.Window()
+ventana.set_default_size(400,400)
+
+box=gtk.VBox(spacing=4)
+
+foridingtk.stock_list_ids():
+imagen=gtk.Image()
+imagen.set_from_stock(id,gtk.ICON_SIZE_BUTTON)
+
+etiqueta=gtk.Label("gtk.STOCK"+id[3:].replace("-","_").upper())
+etiqueta.set_alignment(0.0,0.5)
+
+caja=gtk.HBox()
+
+caja.pack_start(imagen,False)
+caja.pack_start(etiqueta)
+
+box.pack_start(caja)
+
+scroll=gtk.ScrolledWindow()
+scroll.add_with_viewport(box)
+scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
+
+ventana.add(scroll)
+
+ventana.connect('delete-event',gtk.main_quit)
+ventana.show_all()
+gtk.main()
+
+
+if__name__=='__main__':
+run()
diff --git a/recetario/gui/gtk/vbox/index.html b/recetario/gui/gtk/vbox/index.html
index 9c388c351..466b3629a 100644
--- a/recetario/gui/gtk/vbox/index.html
+++ b/recetario/gui/gtk/vbox/index.html
@@ -32,7 +32,7 @@
">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
Ejemplo que muestra el uso de vbox (cajas verticales) para ordenar elementos de forma vertical
-
importgtk
-importsys
-
-classVentana(gtk.Window):
-'''clase que define una ventana que saluda'''
-
-def__init__(self):
-'''constructor, se llama al constructor de la clase padre'''
-gtk.Window.__init__(self)
-
-self.set_default_size(200,200)
-self.set_title("vbox")
-# creamos una caja vertical que contiene elementos
-# de manera vertical
-self.vbox=gtk.VBox()
-# agregamos tres elementos
-self.vbox.pack_start(gtk.Label("uno"))
-self.vbox.pack_start(gtk.Label("dos"))
-self.vbox.pack_start(gtk.Label("tres"))
-
-self.add(self.vbox)
-self.vbox.show_all()
-
-self.connect("delete-event",self.on_delete)
-
-defon_delete(self,window,event):
-'''llamado cuando se cierra la ventana'''
-sys.exit(0)
-
-if__name__=="__main__":
-ventana=Ventana()
-ventana.show()
-gtk.main()
+
importgtk
+importsys
+
+classVentana(gtk.Window):
+'''clase que define una ventana que saluda'''
+
+def__init__(self):
+'''constructor, se llama al constructor de la clase padre'''
+gtk.Window.__init__(self)
+
+self.set_default_size(200,200)
+self.set_title("vbox")
+# creamos una caja vertical que contiene elementos
+# de manera vertical
+self.vbox=gtk.VBox()
+# agregamos tres elementos
+self.vbox.pack_start(gtk.Label("uno"))
+self.vbox.pack_start(gtk.Label("dos"))
+self.vbox.pack_start(gtk.Label("tres"))
+
+self.add(self.vbox)
+self.vbox.show_all()
+
+self.connect("delete-event",self.on_delete)
+
+defon_delete(self,window,event):
+'''llamado cuando se cierra la ventana'''
+sys.exit(0)
+
+if__name__=="__main__":
+ventana=Ventana()
+ventana.show()
+gtk.main()
diff --git a/recetario/gui/gtk/webkiteditor/index.html b/recetario/gui/gtk/webkiteditor/index.html
index b3a48613c..bf37d52ba 100644
--- a/recetario/gui/gtk/webkiteditor/index.html
+++ b/recetario/gui/gtk/webkiteditor/index.html
@@ -25,7 +25,7 @@
-
+
Ir al contenido principal
@@ -59,12 +59,12 @@
Ejemplo de cómo usar webkit para editar páginas HTML como si fuera un editor.
Para probarlo correlo, entra una dirección que empiece con http://, hace foco en alguna parte de la página y ponete a tipear como si fuera un editor de texto común.
Un ejemplo de su uso (tarea del autor encontrar los cambios 😉).
-
importgtk
-importwebkit
-
-classEditor(webkit.WebView):
-'''a webkit editor'''
-
-def__init__(self):
-webkit.WebView.__init__(self)
-self.set_editable(True)
-
-classEditorWindow(gtk.Window):
-'''the editor window'''
-
-def__init__(self):
-gtk.Window.__init__(self)
-self.set_title("webkit editor")
-self.set_default_size(800,600)
-
-self.entry=gtk.Entry()
-self.entry.set_text("http://webkit.org")
-self.entry.connect('activate',self._on_entry_activate)
-self.editor=Editor()
-scroll=gtk.ScrolledWindow()
-scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
-scroll.set_shadow_type(gtk.SHADOW_IN)
-
-scroll.add(self.editor)
-
-vbox=gtk.VBox()
-vbox.pack_start(self.entry,False)
-vbox.pack_start(scroll)
-
-self.add(vbox)
-vbox.show_all()
-
-defload(self,url):
-'''load the given url in the editor and set it to editable'''
-self.editor.open(url)
-
-def_on_entry_activate(self,entry):
-'''callback called when the user hits enter on the entry'''
-self.load(entry.get_text())
-
-if__name__=='__main__':
-window=EditorWindow()
-window.show()
-window.entry.activate()
-gtk.main()
+
importgtk
+importwebkit
+
+classEditor(webkit.WebView):
+'''a webkit editor'''
+
+def__init__(self):
+webkit.WebView.__init__(self)
+self.set_editable(True)
+
+classEditorWindow(gtk.Window):
+'''the editor window'''
+
+def__init__(self):
+gtk.Window.__init__(self)
+self.set_title("webkit editor")
+self.set_default_size(800,600)
+
+self.entry=gtk.Entry()
+self.entry.set_text("http://webkit.org")
+self.entry.connect('activate',self._on_entry_activate)
+self.editor=Editor()
+scroll=gtk.ScrolledWindow()
+scroll.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
+scroll.set_shadow_type(gtk.SHADOW_IN)
+
+scroll.add(self.editor)
+
+vbox=gtk.VBox()
+vbox.pack_start(self.entry,False)
+vbox.pack_start(scroll)
+
+self.add(vbox)
+vbox.show_all()
+
+defload(self,url):
+'''load the given url in the editor and set it to editable'''
+self.editor.open(url)
+
+def_on_entry_activate(self,entry):
+'''callback called when the user hits enter on the entry'''
+self.load(entry.get_text())
+
+if__name__=='__main__':
+window=EditorWindow()
+window.show()
+window.entry.activate()
+gtk.main()
Tengan en cuenta que en Ubuntu inferior 10.04 python-webkit en gtk nececita SI o SI llamar a "gtk.gdk.threads_init()", sino tira error:
-
GLib-ERROR **: The thread system is not yet initialized.
-aborting...
-Cancelado
+
GLib-ERROR **: The thread system is not yet initialized.
+aborting...
+Cancelado
Entonces deberán agregar un "gtk.gdk.threads_init()" antes de llamar a "EditorWindow_()". El final del código les quedará de la siguiente manera:
Esto sirve para modificar los strings que se vayan a imprimir, por ejemplo para agregarles un timestamp o algo similar. En este ejemplo lo usamos para redefinir "2" y "4". Probado en Python 2 y Python 3.
Cómo obtener la IP Pública, usando Python, ejemplo simple.
Nota:Que tengas dirección IP pública no implica que tengas conectividad.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-importurllib
-ip=urllib.urlopen('http://automation.whatismyip.com/n09230945.asp').read()# esta URL puede ser reemplazada con otra que preste similar servicio
-printip
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+importurllib
+ip=urllib.urlopen('http://automation.whatismyip.com/n09230945.asp').read()# esta URL puede ser reemplazada con otra que preste similar servicio
+printip
Ejemplo:
-
sudo/usr/bin/envpythongetip.py
-190.139.27.XXX
+
sudo/usr/bin/envpythongetip.py
+190.139.27.XXX
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
Fe de Erratas: seguramente hay una forma mejor de hacerlo, pero esta funciona correctamente.
diff --git a/recetario/iterarsobrepares/index.html b/recetario/iterarsobrepares/index.html
index bb85f759c..044c24c8b 100644
--- a/recetario/iterarsobrepares/index.html
+++ b/recetario/iterarsobrepares/index.html
@@ -32,7 +32,7 @@
(3, 4)
(5">
-
+
Ir al contenido principal
@@ -66,12 +66,12 @@
diff --git a/recetario/keyboardledsdemo/index.html b/recetario/keyboardledsdemo/index.html
index 52aee7b1e..cf0c10048 100644
--- a/recetario/keyboardledsdemo/index.html
+++ b/recetario/keyboardledsdemo/index.html
@@ -26,7 +26,7 @@
Nota: Si tu teclado es a Baterías (Bluetooth, Wireless), el uso intensivo de este Scri">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/recetario/localsdeunafuncionquelanzounaexcepcion/index.html b/recetario/localsdeunafuncionquelanzounaexcepcion/index.html
index 10ce2a460..505a85340 100644
--- a/recetario/localsdeunafuncionquelanzounaexcepcion/index.html
+++ b/recetario/localsdeunafuncionquelanzounaexcepcion/index.html
@@ -26,7 +26,7 @@
En realidad son los locals de la funcion llamada.
Lo uso para pasarle los locals de la funcion a un template de djan">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Finalmente, memmap tiene el mapa de la memoria, y el detalle por si se quiere generar mapas más detallados o con diferente visualización.
Probablemente para un uso concreto sea necesario extender memmap antes del memmap.sort(), agregando buffers específicos de la aplicación que no caigan dentro de lo consumido por python. Por ejemplo, los objetos mmap tienen asociados grandes pedazos de memoria que no aparecerían en el mapa, y si se usan mucho en la aplicación convendría incluirlos, o buffers significativos utilizados por bibliotecas de extensión.
Este código sólo funciona en CPython, puesto que utiliza el hecho de que id() devuelve la dirección en memoria de un objeto. Eso no es cierto en Jython, PyPy y muchas otras implementaciones.
-
importcPickle
-fromguppyimporthpyasheapy
-_heapy=heapy()
-
-defreport_memmap(mm):
-importre
-frombisectimportbisect_left,bisect_right
-
-mxsz=max(sfora,sinmm)
-
-defusage(mn,mx,mxsz):
-rv=' '
-fora,sinmm[bisect_left(mm,(mn-mxsz-16,0)):bisect_right(mm,(mx+1,0))]:
-ifmn>=mx:
-break
-s+=a+16# add 16 bytes for malloc headers
-ifs<=mn:
-continue
-ifa<mx:
-rv='-'# touched the range, at least fragmented
-ifa>mn:
-# cannot be fully used
-break
-#used up to s
-mn=s
-ifmx<=mn:
-rv='*'# used in full
-returnrv
-
-defbytes(x):
-ifx<1024:
-return'%db'%x
-elifx<1024*1024:
-return'%.2fKb'%(x/1024.0)
-elifx<1024*1024*1024:
-return'%.2fMb'%(x/1024.0/1024.0)
-else:
-return'%.2fGb'%(x/1024.0/1024.0/1024.0)
-
-defsecsize(x):
-rv=4096
-while(x/rv/80)>40:
-rv*=2
-returnrv
-
-defreport(mn,mx,ss):
-smxsz=max(sfora,sinmm[bisect_left(mm,(mn-mxsz-16,0)):bisect_right(mm,(mx+1,0))])
-mp=''.join([usage(i,i+ss,smxsz)foriinrange(mn,mx,ss)])
-rv='%s total, %s per sector\n'%(bytes(mx-mn),bytes(ss))
-rv+=lre.sub('\\1\n',mp)
-rv+="""
- Fragmentation: %.2f%%
- Fragmented sectors: %d
- Contiguous used sectors: %d
- Contiguous free sectors: %d
- """%(mp.count('-')*100.0/len(mp),
-mp.count('-'),
-mp.count('*'),
-mp.count(' '))
-returnrv
-
-defdomap(filterfn):
-ifnotany(filterfn(a)fora,sinmm):
-return'empty'
-mn=min(afora,sinmmiffilterfn(a))
-mx=max(afora,sinmmiffilterfn(a))
-ss=secsize(mx-mn)
-mn=mn/ss*ss
-mx=mx/ss*ss+ss
-returnreport(mn,mx,ss)
-
-lre=re.compile('(.{80,80})')
-
-lomap=domap(lambdaa:a<0x80000000)
-medmap=domap(lambdaa:a>=0x80000000anda<0x100000000L)
-himap=domap(lambdaa:a>=0x100000000L)
-
-returnlomap,medmap,himap
-
-
-defheapStats():
-global_debug_heap
-global_heapy
-
-importStringIO
-
-statdump=StringIO.StringIO()
-heap=_heapy.heap()
-
-try:
-heap.dump(statdump)
-except:
-# ignore exceptions dumping... shit happens
-pass
-
-statdumpu=StringIO.StringIO()
-heapu=_heapy.heapu()
-
-try:
-heapu.dump(statdumpu)
-except:
-# ignore exceptions dumping... shit happens
-pass
-
-statdumpbr=StringIO.StringIO()
-heapbr=heap.byrcs
-
-try:
-heapbr.dump(statdumpbr)
-except:
-# ignore exceptions dumping... shit happens
-pass
-
-refs=None
-try:
-refs=heap.stat
-refs.rows=list(refs.get_rows())
-refs.rows.sort(lambdax,y:-cmp(x.count,y.count))
-
-oc=_heapy.Size.classifier.get_cli().classify
-id_=id
-str_=str
-memmap=[(id_(x),oc(x))forxinheap.nodes]
-except:
-# At least the rest will be useful
-memmap=[]
-
-memmap.sort()
-
-# Generate lowres reports from the memmap in four areas, lo, med, hi and very hi.
-# memory (memory allocations tend to group themselves in those ranges,
-# one is probably memmapped heap, the other is simple allocations and
-# the medium one must be the stack). The very high area is the mmap'd area,
-# where most big arrays end up.
-lomap,medmap,himap=report_memmap(memmap)
-
-# Pickle the memmap, xmlrpclib doesn't like big integers
-memmap=cPickle.dumps(memmap)
-
-defsrepr(x):
-try:
-returnrepr(x)
-exceptException,e:
-return'ERROR: %s'(e,)
-
-rv=dict(
-byclodo=dict(
-reachable=map(srepr,[heap,heap.more,heap.more.more]),
-uncollectable=map(srepr,[heapu,heapu.more,heapu.more.more]),
-statdump=statdump.getvalue(),
-statdumpu=statdumpu.getvalue(),
-refs=srepr(refs)
-),
-byrcs=dict(
-reachable=map(srepr,[heapbr,heapbr.more,heapbr.more.more]),
-statdump=statdumpbr.getvalue()
-),
-memmap=dict(
-detail=memmap,
-lo=lomap,
-med=medmap,
-hi=himap
-)
-)
-
-# return a pickle dump, not by pure xmlrpc
-# (xmlrpc is picky, doesn't support big ints)
-returncPickle.dumps(rv,2)
+
importcPickle
+fromguppyimporthpyasheapy
+_heapy=heapy()
+
+defreport_memmap(mm):
+importre
+frombisectimportbisect_left,bisect_right
+
+mxsz=max(sfora,sinmm)
+
+defusage(mn,mx,mxsz):
+rv=' '
+fora,sinmm[bisect_left(mm,(mn-mxsz-16,0)):bisect_right(mm,(mx+1,0))]:
+ifmn>=mx:
+break
+s+=a+16# add 16 bytes for malloc headers
+ifs<=mn:
+continue
+ifa<mx:
+rv='-'# touched the range, at least fragmented
+ifa>mn:
+# cannot be fully used
+break
+#used up to s
+mn=s
+ifmx<=mn:
+rv='*'# used in full
+returnrv
+
+defbytes(x):
+ifx<1024:
+return'%db'%x
+elifx<1024*1024:
+return'%.2fKb'%(x/1024.0)
+elifx<1024*1024*1024:
+return'%.2fMb'%(x/1024.0/1024.0)
+else:
+return'%.2fGb'%(x/1024.0/1024.0/1024.0)
+
+defsecsize(x):
+rv=4096
+while(x/rv/80)>40:
+rv*=2
+returnrv
+
+defreport(mn,mx,ss):
+smxsz=max(sfora,sinmm[bisect_left(mm,(mn-mxsz-16,0)):bisect_right(mm,(mx+1,0))])
+mp=''.join([usage(i,i+ss,smxsz)foriinrange(mn,mx,ss)])
+rv='%s total, %s per sector\n'%(bytes(mx-mn),bytes(ss))
+rv+=lre.sub('\\1\n',mp)
+rv+="""
+ Fragmentation: %.2f%%
+ Fragmented sectors: %d
+ Contiguous used sectors: %d
+ Contiguous free sectors: %d
+ """%(mp.count('-')*100.0/len(mp),
+mp.count('-'),
+mp.count('*'),
+mp.count(' '))
+returnrv
+
+defdomap(filterfn):
+ifnotany(filterfn(a)fora,sinmm):
+return'empty'
+mn=min(afora,sinmmiffilterfn(a))
+mx=max(afora,sinmmiffilterfn(a))
+ss=secsize(mx-mn)
+mn=mn/ss*ss
+mx=mx/ss*ss+ss
+returnreport(mn,mx,ss)
+
+lre=re.compile('(.{80,80})')
+
+lomap=domap(lambdaa:a<0x80000000)
+medmap=domap(lambdaa:a>=0x80000000anda<0x100000000L)
+himap=domap(lambdaa:a>=0x100000000L)
+
+returnlomap,medmap,himap
+
+
+defheapStats():
+global_debug_heap
+global_heapy
+
+importStringIO
+
+statdump=StringIO.StringIO()
+heap=_heapy.heap()
+
+try:
+heap.dump(statdump)
+except:
+# ignore exceptions dumping... shit happens
+pass
+
+statdumpu=StringIO.StringIO()
+heapu=_heapy.heapu()
+
+try:
+heapu.dump(statdumpu)
+except:
+# ignore exceptions dumping... shit happens
+pass
+
+statdumpbr=StringIO.StringIO()
+heapbr=heap.byrcs
+
+try:
+heapbr.dump(statdumpbr)
+except:
+# ignore exceptions dumping... shit happens
+pass
+
+refs=None
+try:
+refs=heap.stat
+refs.rows=list(refs.get_rows())
+refs.rows.sort(lambdax,y:-cmp(x.count,y.count))
+
+oc=_heapy.Size.classifier.get_cli().classify
+id_=id
+str_=str
+memmap=[(id_(x),oc(x))forxinheap.nodes]
+except:
+# At least the rest will be useful
+memmap=[]
+
+memmap.sort()
+
+# Generate lowres reports from the memmap in four areas, lo, med, hi and very hi.
+# memory (memory allocations tend to group themselves in those ranges,
+# one is probably memmapped heap, the other is simple allocations and
+# the medium one must be the stack). The very high area is the mmap'd area,
+# where most big arrays end up.
+lomap,medmap,himap=report_memmap(memmap)
+
+# Pickle the memmap, xmlrpclib doesn't like big integers
+memmap=cPickle.dumps(memmap)
+
+defsrepr(x):
+try:
+returnrepr(x)
+exceptException,e:
+return'ERROR: %s'(e,)
+
+rv=dict(
+byclodo=dict(
+reachable=map(srepr,[heap,heap.more,heap.more.more]),
+uncollectable=map(srepr,[heapu,heapu.more,heapu.more.more]),
+statdump=statdump.getvalue(),
+statdumpu=statdumpu.getvalue(),
+refs=srepr(refs)
+),
+byrcs=dict(
+reachable=map(srepr,[heapbr,heapbr.more,heapbr.more.more]),
+statdump=statdumpbr.getvalue()
+),
+memmap=dict(
+detail=memmap,
+lo=lomap,
+med=medmap,
+hi=himap
+)
+)
+
+# return a pickle dump, not by pure xmlrpc
+# (xmlrpc is picky, doesn't support big ints)
+returncPickle.dumps(rv,2)
diff --git a/recetario/matrixpythontoy/index.html b/recetario/matrixpythontoy/index.html
index 94df00b9f..33f46b00f 100644
--- a/recetario/matrixpythontoy/index.html
+++ b/recetario/matrixpythontoy/index.html
@@ -29,7 +29,7 @@
def __new__(cls, text, speed):
self = sup'>
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
Para hacerlo andar con threading hay que solo cambiar de donde importamos las cosas, aquí esta la diferencia:
Notar que el pid de quién lanza doer es igual al que imprime doer.
-
diff controlled.py controlledthread.py
-4,5c4,5
-< from multiprocessing import Process
-< from multiprocessing import Queue
----
-> from threading import Thread as Process
-> from Queue import Queue
+
diff controlled.py controlledthread.py
+4,5c4,5
+< from multiprocessing import Process
+< from multiprocessing import Queue
+---
+> from threading import Thread as Process
+> from Queue import Queue
-
importos
-importsys
-
-fromthreadingimportThreadasProcess
-fromQueueimportQueue
-
-classDoer(Process):
-
-def__init__(self,queue,state=None):
-Process.__init__(self)
-self.queue=queue
-self.state=state
-
-def_do_on_start(self):
-print"doint stuff on start"
-print"state:",self.state
-print"pid:",os.getpid()
-print
-
-def_on_end(self):
-print"doint stuff on end"
-print"state:",self.state
-print"pid:",os.getpid()
-print
-
-defrun(self):
-self._do_on_start()
-
-msg=None
-whilemsgisNoneormsg!="exit":
-# blocks here
-msg=self.queue.get()
-print"handling message",msg
-
-# do stuff here according to the message
-ifmsg=="ping":
-print"pong"
-elifisinstance(msg,tuple)andlen(msg)==2:
-action,value=msg
-ifaction=="set-state":
-self.state=value
-print"new state:",self.state
-elifmsg!="exit":
-print"unknown message",msg
-
-print
-
-self._on_end()
-
-defdemo():
-queue=Queue()
-print"creating doer from process",os.getpid()
-doer=Doer(queue,42)
-doer.start()
-queue.put("ping")
-queue.put("foo")
-queue.put(("set-state","hola!"))
-
-queue.put("exit")
-
-doer.join()
-
-if__name__=="__main__":
-demo()
+
importos
+importsys
+
+fromthreadingimportThreadasProcess
+fromQueueimportQueue
+
+classDoer(Process):
+
+def__init__(self,queue,state=None):
+Process.__init__(self)
+self.queue=queue
+self.state=state
+
+def_do_on_start(self):
+print"doint stuff on start"
+print"state:",self.state
+print"pid:",os.getpid()
+print
+
+def_on_end(self):
+print"doint stuff on end"
+print"state:",self.state
+print"pid:",os.getpid()
+print
+
+defrun(self):
+self._do_on_start()
+
+msg=None
+whilemsgisNoneormsg!="exit":
+# blocks here
+msg=self.queue.get()
+print"handling message",msg
+
+# do stuff here according to the message
+ifmsg=="ping":
+print"pong"
+elifisinstance(msg,tuple)andlen(msg)==2:
+action,value=msg
+ifaction=="set-state":
+self.state=value
+print"new state:",self.state
+elifmsg!="exit":
+print"unknown message",msg
+
+print
+
+self._on_end()
+
+defdemo():
+queue=Queue()
+print"creating doer from process",os.getpid()
+doer=Doer(queue,42)
+doer.start()
+queue.put("ping")
+queue.put("foo")
+queue.put(("set-state","hola!"))
+
+queue.put("exit")
+
+doer.join()
+
+if__name__=="__main__":
+demo()
Al efectuar búsquedas en Internet, estamos acostumbrados a que no se distinga entre mayúsculas y minúsculas, y que se ignoren los acentos de las palabras. Para hacer esto en Python, antes que nada necesitamos una función que convierta los strings a la forma especificada. Una que haga lo siguiente:
Unicode define equivalencias entre caracteres, o secuencias de caracteres, de los distintos estándares (ver http://en.wikipedia.org/wiki/Unicode_equivalence). Y define formas normales a las que podemos llevar un texto. Entonces podemos lograr la transformación que queremos haciendo una normalización. Los caracteres se descomponen, ignorando la parte que no es ASCII:
Cómo Detectar y notificar dispositivos USB, usando Python, en Linux, ejemplo simple.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-importglib
-importgudev
-importpynotify
-importsys
-#
-defcallback(client,action,device,user_data):
-device_vendor=device.get_property("ID_VENDOR_ENC")
-device_model=device.get_property("ID_MODEL_ENC")
-ifaction=="add":
-n=pynotify.Notification("USB Device Added","%s%s is now connected "
-"to your system"%(device_vendor,
-device_model))
-n.show()
-elifaction=="remove":
-n=pynotify.Notification("USB Device Removed","%s%s has been "
-"disconnected from your system"%
-(device_vendor,device_model))
-n.show()
-#
-ifnotpynotify.init("USB Device Notifier"):
-sys.exit("Couldn't connect to the notification daemon!")
-#
-client=gudev.Client(["usb/usb_device"])
-client.connect("uevent",callback,None)
-#
-loop=glib.MainLoop()
-loop.run()
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+importglib
+importgudev
+importpynotify
+importsys
+#
+defcallback(client,action,device,user_data):
+device_vendor=device.get_property("ID_VENDOR_ENC")
+device_model=device.get_property("ID_MODEL_ENC")
+ifaction=="add":
+n=pynotify.Notification("USB Device Added","%s%s is now connected "
+"to your system"%(device_vendor,
+device_model))
+n.show()
+elifaction=="remove":
+n=pynotify.Notification("USB Device Removed","%s%s has been "
+"disconnected from your system"%
+(device_vendor,device_model))
+n.show()
+#
+ifnotpynotify.init("USB Device Notifier"):
+sys.exit("Couldn't connect to the notification daemon!")
+#
+client=gudev.Client(["usb/usb_device"])
+client.connect("uevent",callback,None)
+#
+loop=glib.MainLoop()
+loop.run()
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
Fe de Erratas: seguramente hay una forma mejor de hacerlo, pero esta funciona correctamente.
diff --git a/recetario/obtenerbytestransferidos/index.html b/recetario/obtenerbytestransferidos/index.html
index 93b6601b9..cc7910067 100644
--- a/recetario/obtenerbytestransferidos/index.html
+++ b/recetario/obtenerbytestransferidos/index.html
@@ -28,7 +28,7 @@
if interface in line:
data = line.split('%s:' % interf">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
Cómo obtener la Sensación Térmica o Temperatura Aparente usando Python, ejemplo simple.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-importmath
-
-t=20# Temperatura
-v=20# Velocidad del Viento
-st=33+(t-33)*(0.474+0.454*math.sqrt((v))-0.0454*v)
-printst
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+importmath
+
+t=20# Temperatura
+v=20# Velocidad del Viento
+st=33+(t-33)*(0.474+0.454*math.sqrt((v))-0.0454*v)
+printst
Ejemplo:
-
/usr/bin/envpythonst.py
-12.24
+
/usr/bin/envpythonst.py
+12.24
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
Fe de Erratas: seguramente hay una forma mejor de hacerlo, pero esta funciona correctamente.
diff --git a/recetario/obtenerubicaciongeografica/index.html b/recetario/obtenerubicaciongeografica/index.html
index de802cfcf..c63df8ea3 100644
--- a/recetario/obtenerubicaciongeografica/index.html
+++ b/recetario/obtenerubicaciongeografica/index.html
@@ -27,7 +27,7 @@
Requisitos: Base de Datos de Geo-Location en la misma ubicación que el programa, descargarla usando:
wget">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Nota:Depende de la conectividad con Internet usando dirección ip public version 4, se desconoce el comportamiento con ip version 6.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-importurllib
-try:
-importGeoIP
-exceptImportError:
-print(" ERROR: No PYTHON-GEOIP avaliable!!!. ")# que hacer si falla la importacion de la libreria
-pass
-
-# La base de datos GeoLiteCity.dat debe estar en la misma ubicacion que este programa
-gi=GeoIP.open(
-"GeoLiteCity.dat",GeoIP.GEOIP_INDEX_CACHE|GeoIP.GEOIP_CHECK_CACHE)
-
-# Obtiene la IP Publica
-try:
-# esta URL puede ser reemplazada con otra que preste similar servicio
-ip=urllib.urlopen(
-'http://www.whatismyip.com/automation/n09230945.asp').read()
-printip
-except:# que hacer si falla la conectividad
-print("ERROR: Network error!!!. ")
-pass
-
-# Obtiene los datos de la DataBase usando la IP Publica
-data=gi.record_by_name(ip)
-
-# Imprime los datos en la linea de comandos
-printdata
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+importurllib
+try:
+importGeoIP
+exceptImportError:
+print(" ERROR: No PYTHON-GEOIP avaliable!!!. ")# que hacer si falla la importacion de la libreria
+pass
+
+# La base de datos GeoLiteCity.dat debe estar en la misma ubicacion que este programa
+gi=GeoIP.open(
+"GeoLiteCity.dat",GeoIP.GEOIP_INDEX_CACHE|GeoIP.GEOIP_CHECK_CACHE)
+
+# Obtiene la IP Publica
+try:
+# esta URL puede ser reemplazada con otra que preste similar servicio
+ip=urllib.urlopen(
+'http://www.whatismyip.com/automation/n09230945.asp').read()
+printip
+except:# que hacer si falla la conectividad
+print("ERROR: Network error!!!. ")
+pass
+
+# Obtiene los datos de la DataBase usando la IP Publica
+data=gi.record_by_name(ip)
+
+# Imprime los datos en la linea de comandos
+printdata
Colaboración:Si tenes conectividad con internet con ip version 6 NATIVA, puedes documentar tu experiencia aquí.
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
diff --git a/recetario/pasarrecaptcha/index.html b/recetario/pasarrecaptcha/index.html
index ffe5cbdab..8baee883b 100644
--- a/recetario/pasarrecaptcha/index.html
+++ b/recetario/pasarrecaptcha/index.html
@@ -27,7 +27,7 @@
En este caso vamos a probarlo este código con esta demo api: https://www.google.com/recaptcha/api2/demo .">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Realizamos un polling (hace referencia a una operación de consulta constante) para cuando aparezca la imagen de la api demo. Por eso está tomando screenshot de la pantalla cada cierto período de tiempo hasta encontrarlo. Sino lo encuentra después de un cierto valor máximo de tiempo, se detiene la ejecución. Y una vez que encuentra la ventana de la api, hará un rectángulo negro alrededor del objeto "I'm not a robot" detectado y terminará el polling.
-
importpyautogui
-importcv2
-importtime
-
-# Cargar plantilla o imagen de referencia
-plantilla=cv2.imread("./captcha.jpg",0)
-w,h=plantilla.shape[::-1]
-
-# Valores de inicializacion
-min_val=1#min_val ronda en valores menores a 1
-cont=0
-contMax=60
-delay=1#1 segundos
-
-while((min_val>0.015)or(cont==contMax)):#Generelmente 0.015... es el valor que devuelve cuando no encuentra el objeto
-
-# Realizar screenshot de la pantalla para analizarla
-imagen=pyautogui.screenshot()
-# Para guardar cada screenshot
-imagen.save("screenshot.png")
-
-imagenCopy=cv2.imread("screenshot.png",0)
-
-metodo=eval('cv2.TM_SQDIFF_NORMED')
-
-# Aplicar coincidencia de plantillas
-res=cv2.matchTemplate(imagenCopy,plantilla,metodo)
-min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(res)
-
-top_left=min_loc
-bottom_right=(top_left[0]+w,top_left[1]+h)
-
-cont=cont+1
-time.sleep(delay)
-
-print(min_val)
-
-if(min_val<0.015):
-# Colocar un rectangulo en la imagen blanco y negro -> solo tiene un canal por eso aparece 0
-# (El rectangulo queda con una especie de color negro en la imagen)
-cv2.rectangle(imagenCopy,top_left,bottom_right,0,8)
-cv2.imwrite("./coincidencia.png",imagenCopy)
+
importpyautogui
+importcv2
+importtime
+
+# Cargar plantilla o imagen de referencia
+plantilla=cv2.imread("./captcha.jpg",0)
+w,h=plantilla.shape[::-1]
+
+# Valores de inicializacion
+min_val=1#min_val ronda en valores menores a 1
+cont=0
+contMax=60
+delay=1#1 segundos
+
+while((min_val>0.015)or(cont==contMax)):#Generelmente 0.015... es el valor que devuelve cuando no encuentra el objeto
+
+# Realizar screenshot de la pantalla para analizarla
+imagen=pyautogui.screenshot()
+# Para guardar cada screenshot
+imagen.save("screenshot.png")
+
+imagenCopy=cv2.imread("screenshot.png",0)
+
+metodo=eval('cv2.TM_SQDIFF_NORMED')
+
+# Aplicar coincidencia de plantillas
+res=cv2.matchTemplate(imagenCopy,plantilla,metodo)
+min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(res)
+
+top_left=min_loc
+bottom_right=(top_left[0]+w,top_left[1]+h)
+
+cont=cont+1
+time.sleep(delay)
+
+print(min_val)
+
+if(min_val<0.015):
+# Colocar un rectangulo en la imagen blanco y negro -> solo tiene un canal por eso aparece 0
+# (El rectangulo queda con una especie de color negro en la imagen)
+cv2.rectangle(imagenCopy,top_left,bottom_right,0,8)
+cv2.imwrite("./coincidencia.png",imagenCopy)
Este es el resultado:
Una vez detectado el objeto "I'm not a robot" se procede a posicionar el mouse donde éste se encuentre y se procede a dar click.
-
importpyautogui
-
-# Ingresar imagen que debemos buscar
-reCAPTCHAlocation=pyautogui.locateOnScreen('captcha.jpg')
-
-# Posiciones donde se encuentra el elemento buscado
-reCAPTCHApoint=pyautogui.center(reCAPTCHAlocation)
-reCAPTCHAx,reCAPTCHAy=reCAPTCHApoint
-
-# Hacer click en las coordenadas encontradas
-pyautogui.click(reCAPTCHAx,reCAPTCHAy)
+
importpyautogui
+
+# Ingresar imagen que debemos buscar
+reCAPTCHAlocation=pyautogui.locateOnScreen('captcha.jpg')
+
+# Posiciones donde se encuentra el elemento buscado
+reCAPTCHApoint=pyautogui.center(reCAPTCHAlocation)
+reCAPTCHAx,reCAPTCHAy=reCAPTCHApoint
+
+# Hacer click en las coordenadas encontradas
+pyautogui.click(reCAPTCHAx,reCAPTCHAy)
¡Enhorabuena! Lograste superar el reCAPTCHA.
diff --git a/recetario/progressbarurllib2/index.html b/recetario/progressbarurllib2/index.html
index 0722e4ad9..3211574c5 100644
--- a/recetario/progressbarurllib2/index.html
+++ b/recetario/progressbarurllib2/index.html
@@ -27,7 +27,7 @@
from progressbar import Percentage
from progressbar import ">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
Acelera las aplicaciones en Python (JIT), disponible para 32bit.
-
#!/usr/bin/env python
-#-*- coding:utf-8 -*-
-try:
-importpsyco# Speed Up :)
-psyco.full()
-exceptImportError:
-print(" ")
-print(" No PYTHON-PSYCO avaliable, this application will run slower... ")# imprime este mensaje si Psyco no esta disponible
-print(" ")
-pass
-# la aplicacion continuara funcionando si psyco no esta disponible, asi mismo continuara si es 64bit
-########################## imports goes here
-# from foo import bar
+
#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+try:
+importpsyco# Speed Up :)
+psyco.full()
+exceptImportError:
+print(" ")
+print(" No PYTHON-PSYCO avaliable, this application will run slower... ")# imprime este mensaje si Psyco no esta disponible
+print(" ")
+pass
+# la aplicacion continuara funcionando si psyco no esta disponible, asi mismo continuara si es 64bit
+########################## imports goes here
+# from foo import bar
diff --git a/recetario/pythoncard/index.html b/recetario/pythoncard/index.html
index ad33787a0..cd36d93a7 100644
--- a/recetario/pythoncard/index.html
+++ b/recetario/pythoncard/index.html
@@ -26,7 +26,7 @@
PythonCard es un conjunto de herramientas de construcción GUI para crear aplicaciones de escritorio multiplataforma en Windows, Mac OS X, y Linux, usando Python.
La motivación de PythonCa">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Si algo anda mal y no se muestra la pantalla de ejemplos, podemos probar lo siguiente para ver que esta fallando en una consola Python:
-
importwx
-wx.version()# debería imprimir '2.8.7.1 (msw-unicode)' o similar
-
-fromPythonCardimportmodel
-rsrc={'application':{'type':'Application','name':'Minimal',
-'backgrounds':[{'type':'Background','name':'bgMin',
-'title':'Prueba','size':(200,100),'components':[]}]}}
-
-model.Application(model.Background,None,rsrc).MainLoop()
+
importwx
+wx.version()# debería imprimir '2.8.7.1 (msw-unicode)' o similar
+
+fromPythonCardimportmodel
+rsrc={'application':{'type':'Application','name':'Minimal',
+'backgrounds':[{'type':'Background','name':'bgMin',
+'title':'Prueba','size':(200,100),'components':[]}]}}
+
+model.Application(model.Background,None,rsrc).MainLoop()
Debería aparecer una ventanita con título "Prueba".
Además, PythonCard dispone de características de depuración (depurar menú, loggeo, visor de mensajes, visor del espacio nombres, editor de propiedades, shell). Estas opciones se pueden activar al ejecutar los ejemplos para ver cómo funcionan.
@@ -177,29 +177,29 @@
Pythoncard
De no funcionar, se pueden cambiar las opciones de depuración en el menú File, Run Options o ejecutar con el interprete con la opción Run with interpreter
Código completo final del ejemplo:
-
fromPythonCardimportmodel
-fromPythonCardimportdialog
-
-classMyBackground(model.Background):
-
-defon_initialize(self,event):
-# if you have any initialization
-# including sizer setup, do it here
-pass
-
-defon_btnEjecutar_mouseClick(self,event):
-comando=self.components.txtComando.text
-resultado=str(eval(comando))
-self.components.txtResultados.text=resultado
-
-defon_menuFileAyuda_select(self,event):
-dialog.alertDialog(self,
-'Este programa de prueba ejecuta el comando ingresado por el usuario',
-'Ayuda')
-
-if__name__=='__main__':
-app=model.Application(MyBackground)
-app.MainLoop()
+
fromPythonCardimportmodel
+fromPythonCardimportdialog
+
+classMyBackground(model.Background):
+
+defon_initialize(self,event):
+# if you have any initialization
+# including sizer setup, do it here
+pass
+
+defon_btnEjecutar_mouseClick(self,event):
+comando=self.components.txtComando.text
+resultado=str(eval(comando))
+self.components.txtResultados.text=resultado
+
+defon_menuFileAyuda_select(self,event):
+dialog.alertDialog(self,
+'Este programa de prueba ejecuta el comando ingresado por el usuario',
+'Ayuda')
+
+if__name__=='__main__':
+app=model.Application(MyBackground)
+app.MainLoop()
Nota: Por ser un ejemplo se obviaron temas de manejo de excepciones y cuestiones avanzadas. Se pueden descargar los archivos terminados:
diff --git a/recetario/pythonversioncheck/index.html b/recetario/pythonversioncheck/index.html
index b53d3b7d6..ebb6bd2f4 100644
--- a/recetario/pythonversioncheck/index.html
+++ b/recetario/pythonversioncheck/index.html
@@ -26,7 +26,7 @@
if sys.hexversion > 0x02060000: # Python version check
print "\n Python version > 2.6.0\n" # Aca va que hacer si es mayor'>
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Chequear la versión de Python, y salir o imprimir error en funcion de eso.
-
ifsys.hexversion>0x02060000:# Python version check
-print"\n Python version > 2.6.0\n"# Aca va que hacer si es mayor, continua
-else:
-print"\n ERROR: Python version < 2.6.0\n"# Aca va que hacer si es menor, error
+
ifsys.hexversion>0x02060000:# Python version check
+print"\n Python version > 2.6.0\n"# Aca va que hacer si es mayor, continua
+else:
+print"\n ERROR: Python version < 2.6.0\n"# Aca va que hacer si es menor, error
La siguiente macro, detecta el tipo de documento (Calc, Writer, Draw, Impress, etc) desde el cual se ejecuta.
-
# -*- coding: utf-8 -*-
-importuno
-
-defquien_soy():
-doc=XSCRIPTCONTEXT.getDocument()
-msgbox(obtener_tipo(doc))
-return
-
-defobtener_tipo(doc):
-tipo={'com.sun.star.sheet.SpreadsheetDocument':'Calc',
-'com.sun.star.text.TextDocument':'Writer',
-'com.sun.star.presentation.PresentationDocument':'Impress',
-'com.sun.star.drawing.DrawingDocument':'Draw',
-'com.sun.star.sdb.OfficeDatabaseDocument':'Base',
-'com.sun.star.formula.FormulaProperties':'Math',
-'com.sun.star.script.BasicIDE':'Basic'}
-# iteramos entre los tipos de documentos
-fortintipo:
-# validamos si soporta el servicio
-ifdoc.supportsService(t):
-# devolvemos el tipo de documento
-return'Soy %s'%tipo[t]
-# si termina sin encontrar un tipo
-return'No se que tipo soy'
-
-defmsgbox(message):
-ctx=uno.getComponentContext()
-sm=ctx.getServiceManager()
-toolkit=sm.createInstanceWithContext('com.sun.star.awt.Toolkit',ctx)
-msg=toolkit.createMessageBox(
-toolkit.getDesktopWindow(),
-'infobox',
-1,
-'UNOPython',
-str(message))
-returnmsg.execute()
+
# -*- coding: utf-8 -*-
+importuno
+
+defquien_soy():
+doc=XSCRIPTCONTEXT.getDocument()
+msgbox(obtener_tipo(doc))
+return
+
+defobtener_tipo(doc):
+tipo={'com.sun.star.sheet.SpreadsheetDocument':'Calc',
+'com.sun.star.text.TextDocument':'Writer',
+'com.sun.star.presentation.PresentationDocument':'Impress',
+'com.sun.star.drawing.DrawingDocument':'Draw',
+'com.sun.star.sdb.OfficeDatabaseDocument':'Base',
+'com.sun.star.formula.FormulaProperties':'Math',
+'com.sun.star.script.BasicIDE':'Basic'}
+# iteramos entre los tipos de documentos
+fortintipo:
+# validamos si soporta el servicio
+ifdoc.supportsService(t):
+# devolvemos el tipo de documento
+return'Soy %s'%tipo[t]
+# si termina sin encontrar un tipo
+return'No se que tipo soy'
+
+defmsgbox(message):
+ctx=uno.getComponentContext()
+sm=ctx.getServiceManager()
+toolkit=sm.createInstanceWithContext('com.sun.star.awt.Toolkit',ctx)
+msg=toolkit.createMessageBox(
+toolkit.getDesktopWindow(),
+'infobox',
+1,
+'UNOPython',
+str(message))
+returnmsg.execute()
Extraer Un Archivo De Texto Embebido En Un Recurso .qrc
Además de poder embeber imágenes, la librería Qt (y por ende PyQt) también permite incluir otros elementos en su sistema de recursos. La función que se define a continuación permite leer los contenidos de un archivo de texto plano que se encuentre registrado en un archivo .qrc. Cabe agregar que antes de invocar a loadTextFileFromRc() hay que convertir el .qrc a módulo de Python con la herramienta pyrcc4 (por ejemplo, en una terminal de GNU/Linux: $ pyrcc4 -o resources.py resources.qrc). Esto puede ser útil para incorporar al programa una hoja de estilo que se aplique a toda la aplicación.
-
# -*- coding: utf-8 -*-
-
-
-fromPyQt4importQtCore
-
-# El siguiente import realizará el registro de los recursos a PyQt.
-importresources
-
-
-defloadTextFileFromRc(rcPath):
-u"""Extrae el contenido de un archivo de texto incluido en el sistema
- de recursos.
-
- Parámetros:
- rcPath: ruta absoluta del archivo dentro del recurso. Por ejemplo:
- ':/app/css/style.css'.
- """
-
-q_file=QtCore.QFile(rcPath)
-q_file.open(QtCore.QIODevice.ReadOnly)
-q_text_stream=QtCore.QTextStream(q_file)
-content=q_text_stream.readAll()
-q_file.close()
-
-returncontent
-
-
-if__name__=='__main__':
-printloadTextFileFromRc(':/ruta/al/recurso.txt')
+
# -*- coding: utf-8 -*-
+
+
+fromPyQt4importQtCore
+
+# El siguiente import realizará el registro de los recursos a PyQt.
+importresources
+
+
+defloadTextFileFromRc(rcPath):
+u"""Extrae el contenido de un archivo de texto incluido en el sistema
+ de recursos.
+
+ Parámetros:
+ rcPath: ruta absoluta del archivo dentro del recurso. Por ejemplo:
+ ':/app/css/style.css'.
+ """
+
+q_file=QtCore.QFile(rcPath)
+q_file.open(QtCore.QIODevice.ReadOnly)
+q_text_stream=QtCore.QTextStream(q_file)
+content=q_text_stream.readAll()
+q_file.close()
+
+returncontent
+
+
+if__name__=='__main__':
+printloadTextFileFromRc(':/ruta/al/recurso.txt')
diff --git a/recetario/qt/qtimprimirpagina/index.html b/recetario/qt/qtimprimirpagina/index.html
index dcd27a651..d862999ba 100644
--- a/recetario/qt/qtimprimirpagina/index.html
+++ b/recetario/qt/qtimprimirpagina/index.html
@@ -33,7 +33,7 @@
web = QWebView()
web.load(QU">
-
+
Ir al contenido principal
@@ -67,12 +67,12 @@
diff --git a/recetario/qt/qtmultithread/index.html b/recetario/qt/qtmultithread/index.html
index 924a2989c..f2816e760 100644
--- a/recetario/qt/qtmultithread/index.html
+++ b/recetario/qt/qtmultithread/index.html
@@ -30,7 +30,7 @@
#Modificado de la versión original de Mariano Guerra para GTK ">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
Ejemplo de cómo manipular la interfaz gráfica desde múltiples threads.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-#qt_multithread.py
-
-#Modificado de la versión original de Mariano Guerra para GTK ( http://python.org.ar/pyar/GtkMultiThread )
-#Versión para Qt por Ernesto Savoretti
-
-fromPyQt4importQtCore,QtGui
-importtime
-importQueue
-importrandom
-importthreading
-importsys
-
-TEXTS=['eggs','spam','pyar','gtk','qt']
-
-classMolesto(threading.Thread):
-'''un thread que quiere molestar el main thread'''
-
-def__init__(self,cola):
-threading.Thread.__init__(self)
-self.setDaemon(True)
-# self.label = label # no usar en este thread!
-
-self.cola=cola
-
-defrun(self):
-'''metodo principal del thread, duerme un tiempo aleatorio y despues
- pone algo en la cola para que el main thread lo haga'''
-
-whileTrue:
-time.sleep(random.random()*5)
-texto=self.getName()+' '+random.choice(TEXTS)
-printself.getName(),'escribiendo',texto
-self.cola.put(texto)
-
-classVentana(QtGui.QWidget):
-'''ventana con un label, ninguna locura'''
-
-def__init__(self,parent=None):
-QtGui.QWidget.__init__(self,parent)
-self.setGeometry(50,50,640,480)
-self.setWindowTitle('Qt con threads')
-layout=QtGui.QHBoxLayout()
-self.label=QtGui.QLabel(self,text='')
-layout.addWidget(self.label)
-self.setLayout(layout)
-self.cola=Queue.Queue()
-self.hincha_b=Molesto(self.cola)
-
-self.hincha_b.start()
-
-self.timer=QtCore.QTimer(self)
-self.timer.setInterval(100)
-self.timer.timeout.connect(self.queue_manager)
-self.timer.start()
-self.show()
-
-defqueue_manager(self):
-try:
-whileTrue:
-texto=self.cola.get(True,0.1)
-printtexto
-self.label.setText(texto)
-exceptQueue.Empty:
-pass
-
-returnTrue
-
-if__name__=='__main__':
-app=QtGui.QApplication(sys.argv)
-w=Ventana()
-app.exec_()
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#qt_multithread.py
+
+#Modificado de la versión original de Mariano Guerra para GTK ( http://python.org.ar/pyar/GtkMultiThread )
+#Versión para Qt por Ernesto Savoretti
+
+fromPyQt4importQtCore,QtGui
+importtime
+importQueue
+importrandom
+importthreading
+importsys
+
+TEXTS=['eggs','spam','pyar','gtk','qt']
+
+classMolesto(threading.Thread):
+'''un thread que quiere molestar el main thread'''
+
+def__init__(self,cola):
+threading.Thread.__init__(self)
+self.setDaemon(True)
+# self.label = label # no usar en este thread!
+
+self.cola=cola
+
+defrun(self):
+'''metodo principal del thread, duerme un tiempo aleatorio y despues
+ pone algo en la cola para que el main thread lo haga'''
+
+whileTrue:
+time.sleep(random.random()*5)
+texto=self.getName()+' '+random.choice(TEXTS)
+printself.getName(),'escribiendo',texto
+self.cola.put(texto)
+
+classVentana(QtGui.QWidget):
+'''ventana con un label, ninguna locura'''
+
+def__init__(self,parent=None):
+QtGui.QWidget.__init__(self,parent)
+self.setGeometry(50,50,640,480)
+self.setWindowTitle('Qt con threads')
+layout=QtGui.QHBoxLayout()
+self.label=QtGui.QLabel(self,text='')
+layout.addWidget(self.label)
+self.setLayout(layout)
+self.cola=Queue.Queue()
+self.hincha_b=Molesto(self.cola)
+
+self.hincha_b.start()
+
+self.timer=QtCore.QTimer(self)
+self.timer.setInterval(100)
+self.timer.timeout.connect(self.queue_manager)
+self.timer.start()
+self.show()
+
+defqueue_manager(self):
+try:
+whileTrue:
+texto=self.cola.get(True,0.1)
+printtexto
+self.label.setText(texto)
+exceptQueue.Empty:
+pass
+
+returnTrue
+
+if__name__=='__main__':
+app=QtGui.QApplication(sys.argv)
+w=Ventana()
+app.exec_()
diff --git a/recetario/relojdigital/index.html b/recetario/relojdigital/index.html
index 9bf4dbbc4..e7d8792ed 100644
--- a/recetario/relojdigital/index.html
+++ b/recetario/relojdigital/index.html
@@ -36,7 +36,7 @@
root.focus()
root.title("ǝɯıʇ uoɥ'>
-
+
Ir al contenido principal
@@ -70,12 +70,12 @@
Para no depender de programas externos (tené en cuenta que, por ejemplo, ping seguramente no recibe los mismos parámetros en Linux que en Windows), podés intentar abrir un socket a algún servidor externo y enviar algo.
Si el DNS resuelve podés chequear con socket.gethostbyname('google.com').
Método Evaluar: evalua la expresión Python recibida y devuelve su resultado.
Archivo miservidorcom.py
-
# -*- coding: iso-8859-1 -*-
-
-importsys
-
-classMiMiniInterpretePython:
-_public_methods_=['Evaluar']# Métodos a exportar por el servidor COM
-_public_attrs_=['Version']# Atributos a exportar por el servidor COM
-_readonly_attrs_=_public_attrs_# Atributos de solo lectura
-_reg_progid_="MiMiniInterpretePython"# Nombre para Crear el Objeto COM
-# NUNCA copiar el siguiente ID
-# Usar "print pythoncom.CreateGuid()" para crear uno nuevo
-_reg_clsid_="{ECDDA31C-2999-4C77-9778-DDF75FBF81FC}"
-
-def__init__(self):
-# constructor, setear atributos:
-self.Version=sys.version
-
-defEvaluar(self,expresion):
-"Evalua una expresión python y devuelve su resultado"
-returneval(expresion)
-
-
-# Agregar código para que si este script es ejecutado por linea de comando,
-# por Python.exe, se auto-registre
-if__name__=='__main__':
-importwin32com.server.register
-win32com.server.register.UseCommandLine(MiMiniInterpretePython)
+
# -*- coding: iso-8859-1 -*-
+
+importsys
+
+classMiMiniInterpretePython:
+_public_methods_=['Evaluar']# Métodos a exportar por el servidor COM
+_public_attrs_=['Version']# Atributos a exportar por el servidor COM
+_readonly_attrs_=_public_attrs_# Atributos de solo lectura
+_reg_progid_="MiMiniInterpretePython"# Nombre para Crear el Objeto COM
+# NUNCA copiar el siguiente ID
+# Usar "print pythoncom.CreateGuid()" para crear uno nuevo
+_reg_clsid_="{ECDDA31C-2999-4C77-9778-DDF75FBF81FC}"
+
+def__init__(self):
+# constructor, setear atributos:
+self.Version=sys.version
+
+defEvaluar(self,expresion):
+"Evalua una expresión python y devuelve su resultado"
+returneval(expresion)
+
+
+# Agregar código para que si este script es ejecutado por linea de comando,
+# por Python.exe, se auto-registre
+if__name__=='__main__':
+importwin32com.server.register
+win32com.server.register.UseCommandLine(MiMiniInterpretePython)
Para poder usarlo desde otros lenguajes, registrar el servidor COM ejecutando desde línea de comando:
-
pythonmiservidorcom.py--register
+
pythonmiservidorcom.py--register
El siguiente ejemplo en Visual Basic (modulo1.bas) crea el objeto COM ("instanciando" MiMiniInterpretePython) y muestra el atributo (Version), y luego solicita expresiones para evaluar en python.
Archivo modulo1.bas:
-
SubMain()
-
-' Creo el objeto Python exportado por el Servidor COM:
-SetObjetoPython=CreateObject("MiMiniInterpretePython")
-
-' Obtengo un atributo del objeto python:
-Version=ObjetoPython.Version
-MsgBoxVersion,,"Versión de Python:"
-
-Do
-Expresion=InputBox("Ingrese una expresión python para ser evaluada","Ejemplo COM","1+2")
-IfExpresion=""ThenExitSub
-' Llamo al método del objeto python:
-Resultado=ObjetoPython.Evaluar(Expresion)
-MsgBoxResultado,,"Resultado:"
-Loop
-
-EndSub
+
SubMain()
+
+' Creo el objeto Python exportado por el Servidor COM:
+SetObjetoPython=CreateObject("MiMiniInterpretePython")
+
+' Obtengo un atributo del objeto python:
+Version=ObjetoPython.Version
+MsgBoxVersion,,"Versión de Python:"
+
+Do
+Expresion=InputBox("Ingrese una expresión python para ser evaluada","Ejemplo COM","1+2")
+IfExpresion=""ThenExitSub
+' Llamo al método del objeto python:
+Resultado=ObjetoPython.Evaluar(Expresion)
+MsgBoxResultado,,"Resultado:"
+Loop
+
+EndSub
Ejemplo en Visual Fox Pro:
-
* instancio el objeto python via COM:
-ObjetoPython = CREATEOBJECT("MiMiniInterpretePython")
-
-* muestro el atributo versión:
-version = ObjetoPython.Version
-MESSAGEBOX("Versión de Python: " + version, 0)
-
-* muestro el resultado de evaluar una expresión llamando al método vía COM:
-expresion = "' '.join(['hola','mundo'])"
-resultado = ObjetoPython.Evaluar(expresion)
-MESSAGEBOX(resultado, 0)
+
* instancio el objeto python via COM:
+ObjetoPython = CREATEOBJECT("MiMiniInterpretePython")
+
+* muestro el atributo versión:
+version = ObjetoPython.Version
+MESSAGEBOX("Versión de Python: " + version, 0)
+
+* muestro el resultado de evaluar una expresión llamando al método vía COM:
+expresion = "' '.join(['hola','mundo'])"
+resultado = ObjetoPython.Evaluar(expresion)
+MESSAGEBOX(resultado, 0)
Para generar una DLL o EXE y poder distribuir el servidor com sin necesidad de tener instalado Python, usar Py2Exe con el siguiente script de directivas de instalación (ver CrearEjecutableWindows):
Ejecutar Py2Exe para crear el EXE, DLL y demás archivos de distribución (carpeta dist):
-
pythonsetup.pypy2exe
+
pythonsetup.pypy2exe
Luego, registrar el servidor COM por línea de comando:
-
miservidorcom.exe--register
+
miservidorcom.exe--register
o
-
regsvr32miservidorcom.dll
+
regsvr32miservidorcom.dll
Para Descargar Fuentes:
Autor / Autores:
diff --git a/recetario/simplesoapclient/index.html b/recetario/simplesoapclient/index.html
index 800ee659e..9f13ec59a 100644
--- a/recetario/simplesoapclient/index.html
+++ b/recetario/simplesoapclient/index.html
@@ -26,7 +26,7 @@
En este ejemplo se muestra cómo utilizar servicios webs de manera simple (código usado en Factura Electronica)
Utiliza SimpleXmlElement y SimpleSoapClient, manejando de manera simple el pr">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Crea un ícono que cambia de estado según si se esta o no conectado a Internet. Notar que se pueden cambiar más propiedades del botón que las que este simple ejemplo cambia.
-
#!/usr/bin/env python
-#-*- coding:utf-8 -*-
-
-fromTkinterimport*
-importsocket
-root=Tk()
-# Comprobador de conexion a Internet
-inet=Button(root,bitmap='info',fg='green',bg='white')
-inet.pack(pady=20,padx=20)
-#
-try:
-socket.gethostbyname('google.com')
-c=socket.create_connection(('google.com',80),1)
-m=socket.gethostbyname('google.com')
-printm# imprime la ip de google.com para pruebas
-c.close()
-exceptsocket.gaierror:
-print(" ERROR: DNS Error... ")
-inet.config(bitmap='error',fg='red',bg='black')# cambia a un icono de error
-exceptsocket.error:
-print(" ERROR: Connection error... ")
-inet.config(bitmap='error',fg='red',bg='black')# cambia a un icono de error
-#
-root.mainloop()
+
#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+fromTkinterimport*
+importsocket
+root=Tk()
+# Comprobador de conexion a Internet
+inet=Button(root,bitmap='info',fg='green',bg='white')
+inet.pack(pady=20,padx=20)
+#
+try:
+socket.gethostbyname('google.com')
+c=socket.create_connection(('google.com',80),1)
+m=socket.gethostbyname('google.com')
+printm# imprime la ip de google.com para pruebas
+c.close()
+exceptsocket.gaierror:
+print(" ERROR: DNS Error... ")
+inet.config(bitmap='error',fg='red',bg='black')# cambia a un icono de error
+exceptsocket.error:
+print(" ERROR: Connection error... ")
+inet.config(bitmap='error',fg='red',bg='black')# cambia a un icono de error
+#
+root.mainloop()
diff --git a/recetario/tkscrollwhell/index.html b/recetario/tkscrollwhell/index.html
index 72bc61bd7..0c25b0f98 100644
--- a/recetario/tkscrollwhell/index.html
+++ b/recetario/tkscrollwhell/index.html
@@ -30,7 +30,7 @@
root = Tk()
label = La">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
Crea una ventana con Ícono de ventana. Los archivos se pueden pasar a .XBM con Gimp.
-
#!/usr/bin/env python
-#-*- coding:utf-8 -*-
-
-fromTkinterimport*
-root=Tk()
-#
-try:
-root.wm_iconbitmap('@'+'/usr/include/X11/bitmaps/icon')# Ruta al icono, formato .XBM
-exceptTclError:
-print(" ")
-print(" ERROR: Icon File not found... ")# imprime este mensaje si el icono no se encuentra
-print(" ")
-pass
-#
-root.mainloop()
+
#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+fromTkinterimport*
+root=Tk()
+#
+try:
+root.wm_iconbitmap('@'+'/usr/include/X11/bitmaps/icon')# Ruta al icono, formato .XBM
+exceptTclError:
+print(" ")
+print(" ERROR: Icon File not found... ")# imprime este mensaje si el icono no se encuentra
+print(" ")
+pass
+#
+root.mainloop()
Si estamos en Windows es mejor usar la función iconbitmap('Icono.ico') que también se puede pasar la imagen a .ico con Gimp.
-
#!/usr/bin/python
-# -*- coding: utf-8 -*-
-fromTkinterimport*
-root=Tk()
-#
-try:
-root.iconbitmap('Icono.ico')# icono en formato .ico de windows
-exceptTclError:
-print(" ")
-print(" ERROR: Icon File not found... ")# imprime este mensaje si el icono no se encuentra
-print(" ")
-pass
-#
-root.mainloop()
+
#!/usr/bin/python
+# -*- coding: utf-8 -*-
+fromTkinterimport*
+root=Tk()
+#
+try:
+root.iconbitmap('Icono.ico')# icono en formato .ico de windows
+exceptTclError:
+print(" ")
+print(" ERROR: Icon File not found... ")# imprime este mensaje si el icono no se encuentra
+print(" ")
+pass
+#
+root.mainloop()
diff --git a/recetario/tkwizards/index.html b/recetario/tkwizards/index.html
index f0efd9cb4..4b2792207 100644
--- a/recetario/tkwizards/index.html
+++ b/recetario/tkwizards/index.html
@@ -25,7 +25,7 @@
-
+
Ir al contenido principal
@@ -59,12 +59,12 @@
Crea una ventana que muestra el famoso mensaje "Hola mundo".
-
#!/usr/bin/env python3
-#-*- coding:utf-8 -*-
-
-importtkinterastk
-fromtkinterimportttk
-
-classHolaMundoApp(ttk.Frame):
-'''Clase que define una ventana que muestra el "Hola mundo"'''
-
-def__init__(self,master=None):
-ttk.Frame.__init__(self,master)
-
-#Creamos un label
-o=ttk.Label(self,text='Hola PyAr!',anchor='center')
-#Lo agregamos a la ventana.
-o.pack(fill='both',expand=True)
-#Agregamos este frame a la ventana principal (Top level window)
-self.pack(fill='both',expand=True)
-
-#Configuramos la ventana principal
-top=self.winfo_toplevel()
-top.title('Hola mundo')
-top.minsize(width=300,height=200)
-
-
-if__name__=='__main__':
-app=HolaMundoApp()
-app.mainloop()
+
#!/usr/bin/env python3
+#-*- coding:utf-8 -*-
+
+importtkinterastk
+fromtkinterimportttk
+
+classHolaMundoApp(ttk.Frame):
+'''Clase que define una ventana que muestra el "Hola mundo"'''
+
+def__init__(self,master=None):
+ttk.Frame.__init__(self,master)
+
+#Creamos un label
+o=ttk.Label(self,text='Hola PyAr!',anchor='center')
+#Lo agregamos a la ventana.
+o.pack(fill='both',expand=True)
+#Agregamos este frame a la ventana principal (Top level window)
+self.pack(fill='both',expand=True)
+
+#Configuramos la ventana principal
+top=self.winfo_toplevel()
+top.title('Hola mundo')
+top.minsize(width=300,height=200)
+
+
+if__name__=='__main__':
+app=HolaMundoApp()
+app.mainloop()
diff --git a/recetario/validarcuit/index.html b/recetario/validarcuit/index.html
index bd0527bc5..3444600bf 100644
--- a/recetario/validarcuit/index.html
+++ b/recetario/validarcuit/index.html
@@ -25,7 +25,7 @@
-
+
Ir al contenido principal
@@ -59,12 +59,12 @@
Aclaración: que el CUIT sea válido no quiere decir que la persona titular exista y esté habilitada por los organismos correspondientes.
Siempre se debe verificar la vigencia del CUIT en la página de la AFIP (Administración Federal de Ingresos Públicos). Por el momento es una página web, quizas en un futuro ofrezcan un servicio web para automatizar el proceso. Tambien es posible bajarse un padrón (archivo de texto plano), tarea para otra receta 🙂
Crear una ventana para passwords que vibra si la password es incorrecta. El campo de texto oculta los caracteres en pantalla. La vibración es configurable.
Screenshot:
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-fromTkinterimport*
-fromtimeimportsleep
-fromrandomimportrandint
-#
-# correct password is: password
-#
-defcheck(Event=None):
-ifhash(var.get())!=-1767432613:# hash for password
-o=root.geometry()
-l['text']='Wrong Password:\nAttemp will be logged and reported.'
-l.config(fg='red')
-fortimesinrange(50):
-root.geometry("+%d+%d"%(int(root.geometry().split("+")[1])+randint(-69,69),int(root.geometry().split("+")[2])+randint(-69,69)))
-root.update()
-sleep(.05)
-root.geometry(o)
-root.geometry(o)
-root.update()
-else:
-l['text']='OK: Connected to FBI Main Server...'
-print('\nConnected to FBI Main Server...\n')
-l.config(fg='black')
-root.iconify()
-sleep(.25)
-root.deiconify()
-root.geometry()
-var.set("")
-#
-root=Tk()
-root.resizable(0,0)
-root.title("FBI VPN Client")
-root.geometry("+800+350")
-root.wm_attributes("-topmost",1)
-root.focus()
-root.config(bg='#F2F1F0',cursor='hand2')
-var=StringVar()
-l=Label(root,text="FBI Login: Please type your password...",font=('ubuntu',10),bg='#F2F1F0',bd=0,relief='flat',cursor='hand2')
-l.grid()
-a=Entry(root,font=('ubuntu',12,'bold'),show='●',bg='#D7DAED',bd=0,relief='flat',cursor='xterm',highlightcolor='red',textvariable=var)# show = '*'
-a.grid(row=1,column=0,padx=10,pady=10)
-a.bind("<Return>",check)
-a.focus()
-root.mainloop()
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+fromTkinterimport*
+fromtimeimportsleep
+fromrandomimportrandint
+#
+# correct password is: password
+#
+defcheck(Event=None):
+ifhash(var.get())!=-1767432613:# hash for password
+o=root.geometry()
+l['text']='Wrong Password:\nAttemp will be logged and reported.'
+l.config(fg='red')
+fortimesinrange(50):
+root.geometry("+%d+%d"%(int(root.geometry().split("+")[1])+randint(-69,69),int(root.geometry().split("+")[2])+randint(-69,69)))
+root.update()
+sleep(.05)
+root.geometry(o)
+root.geometry(o)
+root.update()
+else:
+l['text']='OK: Connected to FBI Main Server...'
+print('\nConnected to FBI Main Server...\n')
+l.config(fg='black')
+root.iconify()
+sleep(.25)
+root.deiconify()
+root.geometry()
+var.set("")
+#
+root=Tk()
+root.resizable(0,0)
+root.title("FBI VPN Client")
+root.geometry("+800+350")
+root.wm_attributes("-topmost",1)
+root.focus()
+root.config(bg='#F2F1F0',cursor='hand2')
+var=StringVar()
+l=Label(root,text="FBI Login: Please type your password...",font=('ubuntu',10),bg='#F2F1F0',bd=0,relief='flat',cursor='hand2')
+l.grid()
+a=Entry(root,font=('ubuntu',12,'bold'),show='●',bg='#D7DAED',bd=0,relief='flat',cursor='xterm',highlightcolor='red',textvariable=var)# show = '*'
+a.grid(row=1,column=0,padx=10,pady=10)
+a.bind("<Return>",check)
+a.focus()
+root.mainloop()
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
diff --git a/recetario/winbatt/index.html b/recetario/winbatt/index.html
index bc06c7a48..696ab59f2 100644
--- a/recetario/winbatt/index.html
+++ b/recetario/winbatt/index.html
@@ -26,7 +26,7 @@
Esta receta es un ejemplo de cómo utilizar funciones nativas de las bibliotecas de Windows desde Python (usando ctypes).
Por ejemplo, en este caso se usa para consultar el estado de la bat">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
El sudo gráfico universal para escritorios GTK/QT/loquesea, inspirado en el funcionamiento de xdg-open.
-
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# Licence: GPLv3
-# xdg-sudo: Automatically choose "gksudo" or "kdesudo"
-importos
-importsys
-#import antigravity
-importsubprocess
-importre
-ifos.geteuid()==0:# non-root check, because if you are root, all this is pointless
-sys.exit(" ERROR: Do not run as root...\n")
-else:
-print(" You are normal user... \n")
-# Prepare actual command to execute
-parameters=" ".join([re.escape(a)forainsys.argv[1:]])
-# Test which tools exist
-kdesudo=os.path.exists('/usr/bin/kdesudo')
-gtksudo=os.path.exists('/usr/bin/gksudo')
-# If we have at least one of them, check which one to use.
-ifkdesudoorgtksudo:
-ifkdesudoandgtksudo:
-# Test if gnome runs
-process=subprocess.Popen("ps -ae | grep gnome-session",shell=True,stdout=subprocess.PIPE)
-process.wait()
-iflen(process.communicate()[0])>0:
-useGnome=True
-else:
-useGnome=False
-elifkdesudoand(notgtksudo):
-useGnome=False
-elif(notkdesudo)andgtksudo:
-useGnome=True
-# really run it
-ifuseGnome:
-cmd="gksudo "
-else:
-cmd="kdesudo "
-# Run the actual program now
-os.system(cmd+parameters)
-else:
-# we dont have gksudo or kdesudo, OMFG!
-cmd="xterm -e \"echo 'Neither \\\"gksudo\\\" nor \\\"kdesudo\\\" have been found on your machine. Thus, \\\"sudo\\\" is being used. Please leave this window open until the program has finished. Your are asked for your password below.'; sudo "+parameters+"; sleep 1\""
-os.system(cmd)
+
#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Licence: GPLv3
+# xdg-sudo: Automatically choose "gksudo" or "kdesudo"
+importos
+importsys
+#import antigravity
+importsubprocess
+importre
+ifos.geteuid()==0:# non-root check, because if you are root, all this is pointless
+sys.exit(" ERROR: Do not run as root...\n")
+else:
+print(" You are normal user... \n")
+# Prepare actual command to execute
+parameters=" ".join([re.escape(a)forainsys.argv[1:]])
+# Test which tools exist
+kdesudo=os.path.exists('/usr/bin/kdesudo')
+gtksudo=os.path.exists('/usr/bin/gksudo')
+# If we have at least one of them, check which one to use.
+ifkdesudoorgtksudo:
+ifkdesudoandgtksudo:
+# Test if gnome runs
+process=subprocess.Popen("ps -ae | grep gnome-session",shell=True,stdout=subprocess.PIPE)
+process.wait()
+iflen(process.communicate()[0])>0:
+useGnome=True
+else:
+useGnome=False
+elifkdesudoand(notgtksudo):
+useGnome=False
+elif(notkdesudo)andgtksudo:
+useGnome=True
+# really run it
+ifuseGnome:
+cmd="gksudo "
+else:
+cmd="kdesudo "
+# Run the actual program now
+os.system(cmd+parameters)
+else:
+# we dont have gksudo or kdesudo, OMFG!
+cmd="xterm -e \"echo 'Neither \\\"gksudo\\\" nor \\\"kdesudo\\\" have been found on your machine. Thus, \\\"sudo\\\" is being used. Please leave this window open until the program has finished. Your are asked for your password below.'; sudo "+parameters+"; sleep 1\""
+os.system(cmd)
Disclaimer: el uso o no de SheBang/Declaracion de Encoding queda a criterio del usuario.
diff --git a/recetario/xmladiccionario/index.html b/recetario/xmladiccionario/index.html
index 024cc5505..6e4206211 100644
--- a/recetario/xmladiccionario/index.html
+++ b/recetario/xmladiccionario/index.html
@@ -24,7 +24,7 @@
-
+
Ir al contenido principal
@@ -58,12 +58,12 @@
En este ejemplo se muestra cómo convertir un string a una estructura de diccionarios y listas anidadas usando expat. También se proveen dos clases que permiten manipular el resultado como si fueran objetos.
Primero el código
-
importxml.parsers.expat
-
-classXmlParser(object):
-'''a class that parses a xml string an generates a nested
- dict/list structure
- '''
-
-def__init__(self,text):
-'''constructor'''
-self.parser=xml.parsers.expat.ParserCreate()
-self.parser.buffer_text=True
-
-self.result=None
-self.stack=[]
-self.current=None
-
-self.parser.StartElementHandler=self.start_element
-self.parser.EndElementHandler=self.end_element
-self.parser.CharacterDataHandler=self.char_data
-self.parser.Parse(text)
-
-defstart_element(self,name,attrs):
-'''Start xml element handler'''
-ifself.current!=None:
-self.stack.append(self.current)
-
-self.current={}
-
-for(key,value)inattrs.iteritems():
-self.current[str(key)]=value
-
-self.current['tag']=name
-self.current['childs']=[]
-
-defend_element(self,name):
-'''End xml element handler'''
-iflen(self.stack):
-current=self.stack.pop()
-current['childs'].append(self.current)
-self.current=current
-else:
-self.result=self.current
-
-defchar_data(self,data):
-'''Char xml element handler.
- buffer_text is enabled, so this is the whole text element'''
-self.current['childs'].append(data)
-
-classDictObj(dict):
-'''a class that allows to access a dict as an object
- '''
-
-def__init__(self,kwargs):
-'''constructor'''
-dict.__init__(self,kwargs)
-
-def__getattribute__(self,name):
-ifnameinself:
-obj=self[name]
-
-iftype(obj)==dict:
-returnDictObj(obj)
-eliftype(obj)==list:
-returnListObj(obj)
-
-returnobj
-else:
-returnNone
-
-classListObj(list):
-'''a class that allows to access dicts inside a list as objects
- '''
-
-def__init__(self,args):
-'''constructor'''
-list.__init__(self,args)
-
-def__getitem__(self,index):
-ifindex>len(self):
-raiseIndexError('list index out of range')
-
-obj=list.__getitem__(self,index)
-
-iftype(obj)==dict:
-returnDictObj(obj)
-eliftype(obj)==list:
-returnListObj(obj)
-
-returnobj
-
-def__iter__(self):
-'''iterate over the list'''
-
-count=0
-
-whilecount<len(self):
-yieldself[count]
-count+=1
-
-defraw_string(dct_):
-'''return a string containing just the string parts removing all the
- xml stuff'''
-
-defhelper(dct):
-result=[]
-
-forchildindct.childs:
-iftype(child)==strortype(child)==unicode:
-result.append(str(child))
-else:
-result=result+helper(child)
-
-returnresult
-
-return''.join(helper(dct_))
+
importxml.parsers.expat
+
+classXmlParser(object):
+'''a class that parses a xml string an generates a nested
+ dict/list structure
+ '''
+
+def__init__(self,text):
+'''constructor'''
+self.parser=xml.parsers.expat.ParserCreate()
+self.parser.buffer_text=True
+
+self.result=None
+self.stack=[]
+self.current=None
+
+self.parser.StartElementHandler=self.start_element
+self.parser.EndElementHandler=self.end_element
+self.parser.CharacterDataHandler=self.char_data
+self.parser.Parse(text)
+
+defstart_element(self,name,attrs):
+'''Start xml element handler'''
+ifself.current!=None:
+self.stack.append(self.current)
+
+self.current={}
+
+for(key,value)inattrs.iteritems():
+self.current[str(key)]=value
+
+self.current['tag']=name
+self.current['childs']=[]
+
+defend_element(self,name):
+'''End xml element handler'''
+iflen(self.stack):
+current=self.stack.pop()
+current['childs'].append(self.current)
+self.current=current
+else:
+self.result=self.current
+
+defchar_data(self,data):
+'''Char xml element handler.
+ buffer_text is enabled, so this is the whole text element'''
+self.current['childs'].append(data)
+
+classDictObj(dict):
+'''a class that allows to access a dict as an object
+ '''
+
+def__init__(self,kwargs):
+'''constructor'''
+dict.__init__(self,kwargs)
+
+def__getattribute__(self,name):
+ifnameinself:
+obj=self[name]
+
+iftype(obj)==dict:
+returnDictObj(obj)
+eliftype(obj)==list:
+returnListObj(obj)
+
+returnobj
+else:
+returnNone
+
+classListObj(list):
+'''a class that allows to access dicts inside a list as objects
+ '''
+
+def__init__(self,args):
+'''constructor'''
+list.__init__(self,args)
+
+def__getitem__(self,index):
+ifindex>len(self):
+raiseIndexError('list index out of range')
+
+obj=list.__getitem__(self,index)
+
+iftype(obj)==dict:
+returnDictObj(obj)
+eliftype(obj)==list:
+returnListObj(obj)
+
+returnobj
+
+def__iter__(self):
+'''iterate over the list'''
+
+count=0
+
+whilecount<len(self):
+yieldself[count]
+count+=1
+
+defraw_string(dct_):
+'''return a string containing just the string parts removing all the
+ xml stuff'''
+
+defhelper(dct):
+result=[]
+
+forchildindct.childs:
+iftype(child)==strortype(child)==unicode:
+result.append(str(child))
+else:
+result=result+helper(child)
+
+returnresult
+
+return''.join(helper(dct_))
Simplemente creamos un objeto de tipo XmlParser pasándole el string y obtenemos el resultado parseado en la variable result. Si no queremos andar preguntado si las llaves existen antes de accederlas para evitar excepciones podemos usar la clase DictObj que nos permite acceder a las llaves como si fueran atributos, las variables que no existan como llaves contendran None. Acá va un ejemplo en la consola interactiva:
diff --git a/recursos/index.html b/recursos/index.html
index 8767714f1..b49578a07 100644
--- a/recursos/index.html
+++ b/recursos/index.html
@@ -28,7 +28,7 @@
Consejo
ayudanos a pasar esta lista a la nueva sección específica ">
-
+
Ir al contenido principal
@@ -62,12 +62,12 @@
diff --git a/remeras/index.html b/remeras/index.html
index 65a4b93b9..fb532fed5 100644
--- a/remeras/index.html
+++ b/remeras/index.html
@@ -26,7 +26,7 @@
Acá pueden ver el artwork original del cual salieron, creado alguna noche allá en otra">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/remerasv2/index.html b/remerasv2/index.html
index 37546b6f3..41d9c36fa 100644
--- a/remerasv2/index.html
+++ b/remerasv2/index.html
@@ -27,7 +27,7 @@
Esta es toda la info de los sufragios, con las direcciones de mail saneadas:
Por favor, anotá en RemerasV2/PreAnotado">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/rendimientopythonvsjavavsnet/index.html b/rendimientopythonvsjavavsnet/index.html
index 2819bf404..3745e8270 100644
--- a/rendimientopythonvsjavavsnet/index.html
+++ b/rendimientopythonvsjavavsnet/index.html
@@ -35,7 +35,7 @@
Habría que ver b">
-
+
Ir al contenido principal
@@ -69,12 +69,12 @@
diff --git a/ricardokirkner/index.html b/ricardokirkner/index.html
index 720dcba56..a3524bf60 100644
--- a/ricardokirkner/index.html
+++ b/ricardokirkner/index.html
@@ -26,7 +26,7 @@
Para mayor información pueden acceder a mis perfiles online
Página personal: http://www.kirk">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/ricardoquesada/index.html b/ricardoquesada/index.html
index 69ac23c16..330c64a4c 100644
--- a/ricardoquesada/index.html
+++ b/ricardoquesada/index.html
@@ -30,7 +30,7 @@
Me gusta Python: Desarrollos elegantes a alta velocidad
Empecé con BASIC en la Commodore 64, luego aprendí assembler ">
-
+
Ir al contenido principal
@@ -64,12 +64,12 @@
diff --git a/robertoperdomo/index.html b/robertoperdomo/index.html
index c939e1f4e..b6905ffb9 100644
--- a/robertoperdomo/index.html
+++ b/robertoperdomo/index.html
@@ -27,7 +27,7 @@
Desarrollo sistemas para la Universidad Central de Venezuela con web2py.
S">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/santiagobruno/index.html b/santiagobruno/index.html
index 3e3868ee4..5adb96cab 100644
--- a/santiagobruno/index.html
+++ b/santiagobruno/index.html
@@ -26,7 +26,7 @@
Soy rafaelino y vivo en Córdoba. Soy Licenciado en Ciencias de la Computación egresado de Fa.M.A.F. (Universidad Nacional de Córdoba)
Utilizo Pyt">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/santiagopereson/index.html b/santiagopereson/index.html
index 3cc0108fc..5eb3e7230 100644
--- a/santiagopereson/index.html
+++ b/santiagopereson/index.html
@@ -29,7 +29,7 @@
Oveja Eléctrica: un compositor no humano (mucho python, algo de C y programas auxiliares: csound, ecasound">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/santiagosuarezo/index.html b/santiagosuarezo/index.html
index ca6ec0b2c..861911b64 100644
--- a/santiagosuarezo/index.html
+++ b/santiagosuarezo/index.html
@@ -26,7 +26,7 @@
Estoy rindiendo las últimas materias para recibirme de Ingeniero en sistemas de Información en la Universidad Tecnológica Nacional, Regional Rosario.
Arranqué en">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/servidor/index.html b/servidor/index.html
index 29302d6bd..d2cfe5b05 100644
--- a/servidor/index.html
+++ b/servidor/index.html
@@ -37,7 +37,7 @@
Funcionando sobre mod-wsgi, bajo el usuario www-pyar
Sobre Python2.6 por los sitios de pycon (s">
-
+
Ir al contenido principal
@@ -71,12 +71,12 @@
diff --git a/tablaides/index.html b/tablaides/index.html
index 617b608c8..6f431731a 100644
--- a/tablaides/index.html
+++ b/tablaides/index.html
@@ -26,7 +26,7 @@
Tabla comparativa de las features de algunos IDEs disponibles para programar en python.">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
diff --git a/tareaspendientes/index.html b/tareaspendientes/index.html
index b2cfbceb2..f589e5b5b 100644
--- a/tareaspendientes/index.html
+++ b/tareaspendientes/index.html
@@ -29,7 +29,7 @@
Agregar al archivo data/intermap.txt del moinmoin de PyAr las siguiente linea
PyArTrac h">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/terminalesinteractivas/index.html b/terminalesinteractivas/index.html
index 648b4ad65..a144df8a9 100644
--- a/terminalesinteractivas/index.html
+++ b/terminalesinteractivas/index.html
@@ -27,7 +27,7 @@
Python
Esta es la consola por defecto que se instala con Python, para eje">
-
+
Ir al contenido principal
@@ -61,12 +61,12 @@
diff --git a/trabajos/index.html b/trabajos/index.html
index be04948bf..9c894060e 100644
--- a/trabajos/index.html
+++ b/trabajos/index.html
@@ -26,7 +26,7 @@
pero ahora tenemos una sección trabajos donde es mucho más fácil publicar ofertas y postulaciones.
">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
La última versión de Py2 traducido fue 2.7.3, mientras que la última versión de Python liberada es la 3.5.0 Final y está cubierta en nuestra traducción 😉
Las versiones en HTML y los respectivos PDFs se pueden acceder aquí.
El proyecto con todas las fuentes e instrucciones para la generación de los diferentes formatos lo tenemos en GitHub, para obtener una copia hacer:
-
gitclonegit@github.com:PyAr/tutorial.git
+
gitclonegit@github.com:PyAr/tutorial.git
diff --git a/unicode/index.html b/unicode/index.html
index bf358dc81..e52bcc6ae 100644
--- a/unicode/index.html
+++ b/unicode/index.html
@@ -29,7 +29,7 @@
Pragmatic Unicode
The Absolute Minimum Every Software Developer Absolutely, Positively Must">
-
+
Ir al contenido principal
@@ -63,12 +63,12 @@
diff --git a/walikioff/index.html b/walikioff/index.html
index e76317320..376edad70 100644
--- a/walikioff/index.html
+++ b/walikioff/index.html
@@ -26,7 +26,7 @@
Hola! Si llegaste a esta url significa que estás queriendo editar nuestro contenido. ¡Gracias!
Lamentablemente estuvimos recibiendo mucho SPAM y nuestra wiki ">
-
+
Ir al contenido principal
@@ -60,12 +60,12 @@
Del lado de la aplicación, se especifica un punto de entrada (objeto, método, función), con dos parámetros: las variables de entorno (environ y la función para iniciar la respuesta start_response(status,response_headers) que envía el estado y los encabezados), y debe devolver un iterable con los datos para enviar al cliente.
Del lado del servidor, se invoca la aplicación por cada pedido que recibe del cliente HTTP, con las variables de entorno establecidas (estilo CGI)
Ejemplo
-
# Aqui va mi 'Hola PyAr!, pero con WSGI, una maravilla de Python.
-
-fromwsgiref.simple_serverimportmake_server
-
-defhello(environ,start_response):
-start_response('200 OK',[('Content-type','text/plain')])
-return['Hola PyAr!']
-
-httpd=make_server('',8000,hello).serve_forever()
+
# Aqui va mi 'Hola PyAr!, pero con WSGI, una maravilla de Python.
+
+fromwsgiref.simple_serverimportmake_server
+
+defhello(environ,start_response):
+start_response('200 OK',[('Content-type','text/plain')])
+return['Hola PyAr!']
+
+httpd=make_server('',8000,hello).serve_forever()
(copiado de un mail "hello-word" de la lista)
Variables de entorno (diccionario {{{environ}}})
@@ -123,44 +123,44 @@
Web Server Gateway Interface
Igualmente, estos Handlers no son compatibles con WSGI, por eso no recomendaría usar ninguno de ellos directamente, sino a través del wrapper WSGI (con ModPythonGateway) que es un handler "propio" que traduce las peticiones al estandar WSGI. Es algo mucho mas estandar, valga la redundancia, y el día de mañana se puede usar cualquier servidor compatible con python, no solo apache.
Además, puede utilizarse directamente mod_wsgi (ver siguiente sección).
Ejemplos de configuración (tanto en /etc/apache2/... en un archivo .htaccess en el mismo directorio):
-
# handler Publisher:
-# se ejecutará cualquier archivo .py del directorio, llamando a la función de la url:
-# http://www.mysite.com/hello.py/say ejecutara el script hello.py, funcion say
-<Directory/var/www/html/python/>
-SetHandlermod_python
-PythonHandlermod_python.publisher
-PythonDebugOn
-</Directory>
-
-# Handler PSP:
-# se ejecutará cualquier archivo .psp (código python embebido en texto html)
-<Directory/var/www/html/psp/>
-AddHandlermod_python.psp
-PythonHandlermod_python.psp
-</Directory>
-
-# Handler CGI:
-# se ejecutará los scripts .py (scripts normales de python) simil linea de comandos
-<Directory/var/www/cgi-bin/>
-SetHandlermod_python
-PythonHandlermod_python.cgihandler
-OptionsExecCGI
-</Directory>
-
-# handler propio:
-# se ejecuta el archivo myscript.py función handler(req)
-<Directory/mywebdir>
-AddHandlermod_python.py
-PythonHandlermyscript
-PythonDebugOn
-</Directory>
+
# handler Publisher:
+# se ejecutará cualquier archivo .py del directorio, llamando a la función de la url:
+# http://www.mysite.com/hello.py/say ejecutara el script hello.py, funcion say
+<Directory/var/www/html/python/>
+SetHandlermod_python
+PythonHandlermod_python.publisher
+PythonDebugOn
+</Directory>
+
+# Handler PSP:
+# se ejecutará cualquier archivo .psp (código python embebido en texto html)
+<Directory/var/www/html/psp/>
+AddHandlermod_python.psp
+PythonHandlermod_python.psp
+</Directory>
+
+# Handler CGI:
+# se ejecutará los scripts .py (scripts normales de python) simil linea de comandos
+<Directory/var/www/cgi-bin/>
+SetHandlermod_python
+PythonHandlermod_python.cgihandler
+OptionsExecCGI
+</Directory>
+
+# handler propio:
+# se ejecuta el archivo myscript.py función handler(req)
+<Directory/mywebdir>
+AddHandlermod_python.py
+PythonHandlermyscript
+PythonDebugOn
+</Directory>
Para configurar una aplicación wsgi en mod_python:
Para usar WSGI directamente desde apache, existe mod_wsgi, que es un módulo mas reciente, totalmente codificado en C para una mejor performance y estabilidad, que simplifica y resuelve las carencias de mod_python:
Ejemplo 1: ejecutar en el mismo proceso que apache (no independiente, estilo mod_python/php/etc.). En este caso se mapea la url /app al script wsgi app.py:
-
WSGIScriptAlias/app/usr/local/apache/app.py
+
WSGIScriptAlias/app/usr/local/apache/app.py
Ejemplo 2: ejecutar en un proceso (interprete) independiente con un usuario arbitrario diferente de apache (estilo FastCGI, mejorando seguridad y performance):
Con respecto a la diferencia con PHP/PSP, la mayoría de las aplicaciones web en python tienen un solo punto de entrada (un solo .py), que funciona como "despachador", dependiendo de que url te piden, se llama a una función o a otra (generalmente se usa la variable de entorno SCRIPT_NAME o similar, o directamente usar cherrypy, django, turbogears, etc., para que ruteen las peticiones a las clases/funciones que correspondan)
Ejemplo muy simple con WSGI:
-
defApp(environ,start_response):
-"Punto de entrada WSGI"
-ifenviron['SCRIPT_NAME'].endswith("xxxx"):
-respuesta_html=xxxx(environ)
-elifenviron['SCRIPT_NAME'].endswith("yyyy"):
-respuesta_html=yyyy(environ)
-else:
-respuesta_html="<html><body><p>la url es
-inválida!</p></body></html>"
-start_response("200 Ok",[('Content-Type','text/html')])
-yieldrespuesta_html
+
defApp(environ,start_response):
+"Punto de entrada WSGI"
+ifenviron['SCRIPT_NAME'].endswith("xxxx"):
+respuesta_html=xxxx(environ)
+elifenviron['SCRIPT_NAME'].endswith("yyyy"):
+respuesta_html=yyyy(environ)
+else:
+respuesta_html="<html><body><p>la url es
+inválida!</p></body></html>"
+start_response("200 Ok",[('Content-Type','text/html')])
+yieldrespuesta_html
Entonces, si te llaman www.tuservidor.com/aplicacion/xxxx haces una cosa (xxxx), mientras que si llaman a www.tuservidor.com/aplicacion/yyyy haces otra (yyyy). En comparación con php/psp, sería como llamar a www.tuservidor.com/aplicacion.psp?funcion=xxxx o www.tuservidor.com/aplicacion.psp?funcion=yyyy.
Esto es un poco mas difícil de entender, pero a la larga es mas flexible porque no te limita a tener un archivo (estructura "física") para cada dirección (estructura "lógica"), limpiando un poco la url de extensiones .py, signos de interrogación, etc. , haciéndolas mas fáciles de entender para el usuario.
diff --git a/wwwhexactacom/index.html b/wwwhexactacom/index.html
index fc768cc4d..62a26fabe 100644
--- a/wwwhexactacom/index.html
+++ b/wwwhexactacom/index.html
@@ -25,7 +25,7 @@
-
+
Ir al contenido principal
@@ -59,12 +59,12 @@