Apuntes De Python
Gestores de paquetes
- pip
-
El gestor de paquetes por defecto de python
- pipx
-
Un instalador pensado para aplicaciones CLI en Python, se encarga de instalar cada aplicación en un virtualenv independiente.
- Cosas instaladas con
pipx
en mi sistema son por ejemplo:pypisearch
,ranger
okikit
-
Los virtualenv creados por pipx quedan en
~/.local/pipx/venvs
- conda
-
El instalador de las distribuciones Anaconda y Miniconda
Gestores de entornos virtuales
En cualquier distribución de Linux disponemos de un Python del
Sistema, es el Python que viene instalado por defecto con el S.O. (podemos averiguar cual es ejecutando: which python
y/o python -V
) En mi caso concreto, usando Linux Mint el Python del sistema es el 2.7.18. Una versión anticuada, pero que es mejor no tocar ya que habrá partes del sistema operativo que dependan de ella.
Podemos tener más versiones de Python instaladas en nuestro S.O. (yo ahora mismo tengo disponibles python3
, python3.8
y python3.9
) pero solo una de ellas es el Python del Sistema, el Python que se ejecuta por defecto.
Instalar paquetes de Python en el Python del Sistema no es nada recomendable. Si instalamos versiones incompatibles de paquetes o actualizamos versiones instaladas podemos perturbar el funcionamiento de alguna parte del propio sistema operativo. Desinstalar paquetes en Python siempre es una aventura (a menudo imposible) así que si tenemos problemas la solución puede ser extremadamente complicada (a mi ya me tocó reinstalar Linux entero por enredar sin saber).
venv
, virtualenv
o pipx
.Además de todo lo anterior es muy probable que la versión del Python del Sistema no sea la versión que queremos usar con nuestro proyecto. O podemos estar interesados en usar varias versiones diferentes de Python, ya sea para desarrollo o para ejecutar distintas aplicaciones.
Un gestor de entorno python nos permitirá:
- Instalar python en un entorno aislado
- Instalar multiples versiones de python; cada una en su propio entorno, de forma que no interfieran entre si
- Instalar distintas combinaciones de paquetes
- Cambiar de versión de python sin más que cambiar de entorno
virtualenv y virtualenvwrapper
virtualenv es probablemente la herramienta más básica para crear entornos virtuales para Python y virtualenvwrapper es un frontend que facilita mucho su uso.
La idea es muy simple, se crea una instalación de Python independiente en un directorio dedicado y se modifica el PATH
para que ese Python sea prioritario.
virtualenvwrapper centraliza todos los entornos virtuales (es decir los directorios con los distintos python), en un único directorio de entornos (especificado con $WORKON_HOME
)
En el Python 3 que viene con mi Linux Mint yo instalo:
|
|
En el fichero ~/.profile
añadimos:
|
|
Además en zsh
uso el bundle virtualenvwrapper
y tengo parcheado el prompt del tema del zsh y el prompt del zsh-git-prompt (Ver dotfiles) para visualizar en el prompt el entorno virtual activo (si hay alguno activado claro)
Este bundle de zsh también se encarga de activar automáticamente el entorno virtual si cambiamos a un directorio de proyecto con el mismo nombre (se considera directorio de proyecto si está controlado por git). Aunque también hay formas de asociar un directorio de proyecto al crear un entorno virtual, como veremos.
|
|
pyenv
pyenv
con pyvenv
pyenv es mucho más potente que virtualenv y además podemos integrar tanto virtualenv como virtualenvwrapper con pyenv.
Mi ciclo de trabajo con pyenv:
- Instalar versiones de Python en mi máquina con pyenv
- Crear entornos virtuales basados en esas versiones, con el plugin virtualenv de pyenv
- Asignar los entornos virtuales a proyectos (normalmente con
pyenv local <entorno>
Instalamos las dependencias en el sistema:
|
|
Y a continuación instalamos el pyenv-bundle
en Antigen, añadiendo la linea:
antigen bundle mattberther/zsh-pyenv
a nuestro fichero ~/.zshrc
La instalación que hace el plugin de zsh
es muy completa, instala pyenv con todos los plugins.
Evidentemente este método de instalación solo vale si usas zsh
, aquí tienes una alternativa (que no he probado) o puedes currarte una instalación siguiendo las instrucciones oficiales en el github del proyecto pyenv
zsh-pyenv
se encargará de la instalación de pyenv
Tenemos que asegurarnos de dejar configurada la activación de pyenv
en nuestros fichero .profile
y .zshrc
(o .bashrc
)
En ~/.profile
añadimos las siguientes lineas (las lineas comentadas se dejan como referencia por que ya lo configura el plugin de zsh):
|
|
En ~/.zshrc
no debería ser necesario añadir nada por que se supone que el plugin de oh-my-zsh se encarga de activar todo pyenv, pero en mi instalación el autocompletado de comandos de pyenv solo funciona si añado este código:
|
|
Si quieres echar un ojo a las versiones de Python que puedes instalar en tu sistema ejecuta pyenv install --list
(hay 490 versiones en el momento de escribir esto)
|
|
pyenv global
Me he creado un entorno virtual para usar como pyenv global:
- Creamos un entorno basado en la versión oficial de Python más reciente (3.9.6 al escribir esto)
- En el nuevo entorno instalamos las últimas versiones de pip, setuptools, pipx, virtualenv y virtualenvwrapper
|
|
Parece que los plugins pyenv
y virtualenvwrapper
de oh-my-zsh
no son compatibles. El plugin de oh-my-zsh
para virtualenvwrapper intenta activar el virtualenvwrapper haciendo un source virtualenvwrapper.sh
, pero ahora tenemos un shimm que intercepta la llamada y no funciona correctamente, de hecho aborta el terminal.
No parece aconsejable activar simultaneamente los dos plugins así que el plugin de virtualenvwrapper
queda desactivado en el fichero .zshrc
Para poder activar el virtualenvwrapper correctamente via el shimm, añadimos el siguiente alias:
|
|
Esto funcionará correctamente siempre y cuando en el python activo tengamos instalado virtualenvwrapper claro está.
pyenv y emacs
Referencias
- Una referencia muy completa Getting started with lsp-mode for Python
En Emacs usamos LSP. Para Python necesitamos instalar python-lsp-server Mucho ojo, no hay que instalar Palantir (python-language-server), que se considera obsoleta.
Con el siguiente comando instalamos en nuestro Python activo (por ejemplo el Python global) el servidor pylsp
y todos sus providers (ver el github del proyecto)
|
|
Si queremos que nuestro editor Emacs edite código Python a plena potencia necesitaremos instalar este paquete en el Python activo del proyecto en el que trabajemos.
Para simplificar la creación de nuevos entornos creamos el alias myve
que podemos invocar una vez creado nuestro nuevo entorno virtual para instalar los paquetes mínimos:
|
|
pyenv y conda
Ojo, por que los entornos virtuales de Anaconda y Miniconda parece que hay que crearlos con conda
para que funcionen bien. (ver artículo).
Supongamos que tenemos instalada la versión anaconda3-2021.11
. Ejecutaríamos:
|
|
pyenv y poetry
PENDIENTE DE MIRAR
pyenv y pip-tools
PENDIENTE DE MIRAR
Instalando paquetes en Python
Muy importante leerse el tutorial oficial Installing Packages
Instalando un paquete desde el shell de python
|
|
Modulos en Python
Todos los lenguajes de programación modernos soportan la programación modular. Cualquier programa minimamente complicado hace uso de “módulos” que encapsulan diferentes funcionalidades.
En Python cualquier fichero con código Python puede considerarse un módulo. Podríamos acceder a cualquier código de cualquier fichero mediante un import
(hay muchas formas de hacer el import
)
Por ejemplo si en un programa hacemos un import math
podremos acceder a los simbolos (math.pi
) o funciones (math.sin(math.pi/2)
) definidos en ese módulo desde nuestro código (usando el prefijo del módulo que es math.
en este ejemplo)
Diferentes tipos de import
Packages (Paquetes)
El siguiente nivel de modularidad en Python es el package
. Cuando una aplicación o biblioteca se complica y empieza a tener un gran número de módulos podemos organizarlos en paquetes (package
)
Basicamente un package
es un directorio en el que dejamos módulos (ficheros con código Python) pero cumpliendo ciertas condiciones.
Exceptions in python
|
|
Reverse string in Python
|
|
Minidom
- Acceder a un atributo
|
|
- Acceder a la lista de atributos
|
|
tkinter
tkinter (Tk interface) es una biblioteca de Python para usar el Tcl/Tk GUI Toolkit. Un conjunto de herramientas clásico para desarrollar interfaces gráficos de usuario, y que está disponible en practicamente todas las distribuciones de *nix, incluyendo macOS, también hay disponibles versiones para Windows.
Es bastante probable que tkinter esté incluido en tu Python de sistema (el python que venga por defecto en tu Linux), o que se haya instalado como dependencia de otros programas de tu Linux lo puedes probar rápidamente sin más que ejecutar desde el terminal:
|
|
Deberías ver una ventana gráfica con la versión de Tcl/Tk (en mi linux es la 8.6) y un par de botones de demostración (con el botón Quit
terminas el programa de demo)
En el caso de que no esté instalado te fallará el import
, si lo quieres instalar en el python de sistema en Debian y derivadas el comando debería ser algo parecido al siguiente comando, que es el que hay que ejecutar en Ubuntu y derivadas:
sudo apt install python3-tk
Aprendiendo tkinter
Creamos un virtualenv:
|
|
Probamos que todo va bien
|
|
Vamos a echar un ojo a un programa completo
|
|
Lo mismito pero con OOP
|
|
widgets
- Todos los widgets tienen un padre (excepto la ventana root)
- Todos los widgets son de alguna clase Widget roundup
- Las opciones de un widget controlan su comportamiento (incluida su visualización) Evidentemente dependen también de cual es su clase. Se intenta que los nombres de los atributos sean consistentes entre clases.
- Puedes ver toda la configuración de un widget con
button.configure()
- Puedes cambiar una opción con
button['text']=newvalue
o conbutton.configure(text=newvalue)
Con este programilla podemos ver toda la jerarquía de widgets
|
|
Gestión de la geometría
grid es más moderno que pack usa grid
Event handling
- Los eventos son tratados por el event handling loop que no debe ser bloqueado.
- Las cosas interesantes se consiguen asociando command callbacks a eventos
1 2 3 4 5 6 7 8 9 10 11 12
from tkinter import * from tkinter import ttk root = Tk() l =ttk.Label(root, text="Starting...") l.grid() l.bind('<Enter>', lambda e: l.configure(text='Moved mouse inside')) l.bind('<Leave>', lambda e: l.configure(text='Moved mouse outside')) l.bind('<ButtonPress-1>', lambda e: l.configure(text='Clicked left mouse button')) l.bind('<3>', lambda e: l.configure(text='Clicked right mouse button')) l.bind('<Double-1>', lambda e: l.configure(text='Double clicked')) l.bind('<B3-Motion>', lambda e: l.configure(text='right button drag to %d,%d' % (e.x, e.y))) root.mainloop()
Ejemplos
Un campo entrada de texto
|
|
Checkbuttons
|
|
Estudio
- Análisis de un ransomware
- Pomodoro en python
- Tkinter en RealPython
- Another Tkinter tutorial
- Tercer tutorial para Tkinter
Create http server
Comparte los ficheros de la carpeta
|
|
Decorators
Static method vs Classmethod
Referencias
Curso de Python
Info do curso
Sabados 11.00 - 13.00 horas
- @caligari (é mais de práctica)
- @salvari (é mais de teoría)
Estructura do curso
- Teoría e práctica
- Práctica “de deberes”
- Preguntas dúbidas e tertulia
Dinámica do curso:
- Non se graba
- Non hai transparencias, o profe teórico é un vago (tamén intenta ser presumido e impaciente)
- Apuntes colaborativos
- Iremos incorporando ao libro exemplos e notas que vexamos útiles
Bricolabs
Documentación do curso
- Gitlab de Ekaitz: https://gitlab.com/ElenQ/Publishing/python/-/tree/master/es
- Tradución ao galego (coordinador: Rafa Gaioso Melisa)
- https://pad.disroot.org/p/curso_python_memoria.md
Outros enlaces de interese
- Itinerario formativo con ou sen mentorización: https://exercism.io/tracks/python
Apuntes sesión 01
Algo de Historia
Fai 30 anos… a explosión dos intérpretes:
- Perl
- Larry Wall (1987)
- Killer app:
- CGI perlcgi integrado no código de Apache.
- Linguaxe pegamento para sysadmins
- Perl Template Toolkit
- Python
- Guido Van Rosum (1991) Benevolent Dictator for Life (https://en.wikipedia.org/wiki/Benevolent_dictator_for_life), un título moi usado no mundo hacker e inventado para Guido
- Killer app:
- Zope, Plone, Django, Calibre, Web2py
- Integración con Gimp, con KiCAD, con FreeCAD, con ….
- Big Data, iPython (agora Jupyter), Machine Learning, Deep Learning
- PHP
- Rasmus Lerdorf (1995)
- Killer app:
- Wordpress
- Milleiros de aplicacións web
- Ruby
- Matz Matsumoto (1995)
- Killer app:
- Ruby on rails
- Pouco coñecido en occidente pero super implantado en Asia
Las tres virtudes del programador
(según Larry Wall, creador do Perl)
- Pereza
- “La virtud que te hace esforzarte para reducir tu gasto global de energía. Hace que escribas programas que te ahorran trabajo y te hace documentar esos programas para que no tener que contestar preguntas acerca de como funcionan.”
- Impaciencia
- “El ansia que sientes cuando el ordenador remolonea. Esto hace que escribas programas que no sólo satisfacen tus necesidades si no que se anticipan a ellas. O al menos lo intentan.”
- Orgullo
- “La virtud que te hace escribir (y mantener) programas intachables, de los que el resto de la gente no pueda hablar mal.”
O lema de Perl: TIMTOWTDI “There is more than one way to do it”, ou sexa, hai moitas formas de facelo (e ademais eso mola moito)
A resposta de Python (e decir, de Guido, que é colega de Larry)
“There should be one — and preferably only one — obvious way to do it.” Normalmente hai unha forma obvia e óptima de facelo (é iso mola moito mais de cara a manter o software)
Qué é python?
- Linguaxe de programación
- Interpretado non compilado
Pros
- Simplicidade
- Versatilidade facilidade de uso e desenrolo rápido
- Software libre e aberto, cunha comunidade moi activa
- Un conxunto de bibliotecas enorme e super completo
- Excelente para prototipos (código compacto)
Limitacións o Desventaxas do Python
- Limitacións de velocidade (é interpretado e iso sempre penaliza a velocidade)
- Problemas có Threading (estou empezando a programar, non me importa)
- Non ten implantación destacable en dispositivos móbiles: Android e IOS (pero mira Kivy se estás moi interesado neste campo)
Pingas de Python:
- Terminal vitaminado para python:
bpython3
ouptpython
- Axuda interactiva:
help('string')
- Saber ruta do intérprete en linux:
which python
ouwhich python3
- Script, empeza coa línea shebang, para decirlle que intérprete usar
Ou tamén
1
#!/ruta al intérprete
1
#!/usr/bin/env python3
- Ver “posición da memoria” (en realidade
id
devolve un identificativo único) da variable1
hex(id(a))
- saber o tipo dunha variable:
type(variable)
Mutabilidad:
- A tupla e inmutable
- A lista e mutable
Estilo de programación
- Readability counts (the zen of python)
- El código se lee mucho más a menudo de lo que se escribe
- Reglas de estilo pep8
- Reglas de docstring (los comentarios de documentación) pep257
Tipos de datos
|
|
Operadores
|
|
Apuntes sesión 02
Bucle for
El bucle for
clásico se puede conseguir facilmente con la función range()
|
|
En los bucles for
y while
se pueden usar las palabras clave continue
, break
y else
:
|
|
OJO
El else
para bucles es una de las características más controvertidas
de Python, el propio Guido dijo que nunca debió incluirla en la
especificación del lenguaje, o al menos que se debió usar otra palabra
que no fuera else
Para un while
sería lo mismo
|
|
Las sentencias de tratamiento de excepciones también tiene else
y
además una clausula finally
|
|
Apuntes sesión 03
Sábado, 18/04/2020 Exercism
Neste enlace tedes a páxina de exercism, onde vos podedes dar de alta (opcional) para facer o track de Python.
https://exercism.io/tracks/python/exercises
Se vos dades de alta en exercism, veredes que hai instruccións para instalar un cliente de linea (de linea de comandos) que permite descargar os exercicios e subir as solucións. E moi doado de instalar non vos preocupedes. (Guía de instalación)
Lembrade traballar en un entorno virtual, se queredes instalar o módulo pytest que suxiren en exercism, facedeo dentro do voso virtualenv, poderíades facer algo como:
|
|
Lembrade o comentado no curso, agora estamos escribindo “Baby Python”, non vos preocupedes do estilo ou se o facedes ben ou mal, o importante é que funcione.
O voso python mellorará coa práctica e lendo código de outros.
Lembrade tamén que haberá bibliotecas para facer todo tipo de cousas, é imposible coñecelas todas. Có tempo coñeceredes as que usedes mais frecuentemente, pero non serán moitas. Sempre hai que apoiarse na documentación a través de internet.
Solución exercicio 1 (Adiviña o número)
|
|
Solución exercicio 2: Simular tiradas de dados
|
|
Apuntes sesión 04
- Módulo
- Escritos normalmente para ser importados
- Script
- Escritos normalmente para ser ejecutados desde la linea de comandos
- Programa
- Seguramente compuesto por varios módulos
Importar módulos
|
|
Scopes (LEGB)
Estrictamente hablando Python recorre los siguientes scopes
cuando busca un símbolo
- Local
- Nombres asignados dentro de una función (también aplica a lambdas) y que no se preceden con la palabra clave global
- Enclosing-function
- Nombres asignados dentro de cualquier función padre en una cadena de funciones anidadas. De dentro hacia fuera e incluye lambdas
- Global (a nivel de módulo)
- Nombres asignados en el nivel superior de un modulo (fichero) de python. O asignados dentro de una función pero precedidos de la palabra clave global
- Built-in (Python)
- Nombre preasignados en el built-in por el intérprete de Python. P.ej: open, range, SyntaxError, etc
global
y nonlocal
Algunos namespaces:
- Global
- Módulos
- Clases
- Generadores
- Función
Utilizar .get
para crear un contador cuando no has definido el número inicial del parámetro que quieres contar:
.get(loquesea, 0)
: Devuelve lo que sea si existe, y si no, devuelve 0.
palabrainterna
Apuntes sesión 05
Flujo de programa
lambdas
Son funciones “telegráficas” que se usan a veces para acortar el código.
En general las lambdas deberían ser de un solo uso, y en casos muy particulares donde necesitamos una función muy simple (casí siempre como parámetro para otra función o una list comprehension
Si te encuentras peleando para implementar una lambda compleja, es casi seguro que deberías dejarlo y emplear una función normal.
Parámetros de funciones
Tenemos que distinguir entre dos escenarios: antes de Python 3.8 y después de Python 3.8.
Hasta ahora teníamos:
Aquí tenemos una funcíon definida con tres parámetros, uno de ellos (c) con un valor por defecto
Al llamar la función c es opcional puesto que tiene valor por defecto
Cualquier parámetro lo podemos pasar por posición, pero todos los posicionales tienen que ir desde el principio. En cuanto pasemos un parámetro por nombre ya no podemos añadir ninguno posicional.
Cualquier parámetro lo podemos pasar también por nombre, siempre dejando los posicionales (si los hay) al principio en su lugar. En cuanto pasemos un parámetro por nombre ya no podemos añadir ninguno posicional.
|
|
Si definimos la función como
|
|
Sigue en pie la regla de que TODOS los parámetros posicionales tienen
que ir al principio. Podemos pasar todos los parámetros posicionales
que queramos, los tres primeros se asignan a: a, b y c respectivamente
el resto se capturan en la tupla args
. Por convención se emplea la
tupla llamada args
. Podríamos emplear cualquier otro nombre para la
tupla, pero dificultaríamos la inteligibilidad del código por parte de
otros programadores.
|
|
Esta función admite dos párametros posicionales, el resto de parámetros adicionales tienen que ser con nombre y quedan capturados en el diccionario kargs
|
|
Esta función admite dos o mas parámetros posicionales, los dos
primeros se asignan a a
y b
, el resto se capturan en la tupla
args
. También podemos meter todos los parámetros que queramos con
nombre, se capturan en el diccionario kargs
Desde Python versión 3.8 además tenemos dos separadores de paramétros
/
y *
En el caso de que usemos los separadores:
- A la izquierda de
/
son parámetros posicionales puros, no se puede llamarlos por nombre - A la derecha de
*
son parámetros por nombre obligatoriamente - Lo que va en el medio de los dos simbolos, pueden ser usados posicionalmente o por nombre
|
|
OJO: ¡No usar parámetros mutables en la definicion de las funciones!
Algunos ejemplos de paso de parámetros con valor por defecto:
Con valor por defecto inmutable. No tiene problemas.
|
|
Con un valor que varía a lo largo de la ejecución del programa (problema: no va a variar)
Pasamos como parámetro por defecto la hora actual, pero la llamada a ctime solo se ejecuta una vez al inicio del intérprete de python, no cada vez que llamamos a la función
|
|
Pasamos como parámetro un valor mutable (muy mala idea, no lo hagais)
Pasamos como valor por defecto la lista vacía, en la práctica pasar un valor por defecto equivale a crear un closure, la función mantiene su contexto a lo largo del ciclo de vida del programa con una referencia al valor por defecto del parámetro alist (que es una lista y por tanto mutable)
Cada vez que llamamos a la función sin parámetros la función añade una nueva cadena ‘uno’ a la lista almacenada en el closure como “valor por defecto de alist”
Si pasamos un parámetro, la cosa cambia, python crea una nueva lista en memoria y asigna la referencia a esa lista como parámetro de la función, con lo cual se ejecuta como esperamos. Al terminar la referencia a esa lista que pasámos como parámetro no se almacena en el closure de la función y si no hay otras referencias a ella en el programa será reclamada por el garbage colector.
|
|
Solución al problema anterior (probada)
|
|
Funciones pasadas como parámetros. Composición de funciones:
|
|
Funciones anidadas:
|
|
Funciones anidadas y paso de funciones como parámetro
|
|
Closures (o cierres)
Los closures son funciones que mantienen un “entorno” en el que “recuerdan” variables. En el ejemplo de abajo
|
|
Decoradores
|
|
OOP - Programación orientada a objetos
La programación orientada a objetos se basa en cuatro principios básicos
- Encapsulado
- Abstracción
- Herencia
- Polimorfismo
Código de la sesión 06:
|
|
Docker y Python
Podemos usar Docker para tener proyecto aislados en sus contenedores. Esto nos puede simplificar la vida a la hora de gestionar dependencias, versiones de Python o distintas configuraciones.
Containers
Vamos a crear un contenedor con una aplicación muy chorras. Para crear nuestro contenedor suponemos que creamos el directorio app
en alguna parte de nuestro sistema de ficheros.
|
|
El contenido del fichero server.py
tendría esta pinta:
|
|
Como requisito necesitamos tener Flask
instalado así que en requirements.txt
tedremos
|
|
Ahora vamos a definir como se construye la imagen Docker con nuestro dockerfile
:
|
|
Nuestro dockerfile
:
- parte de la imagen oficial para Python 3.10.9
- define el directorio de trabajo
/code
(en el contenedor) - copia el fichero
requirements.txt
desde el host (nuestro ordenador) al directorio de trabajo del contenedor - copia el directorio
src/
al directorio de trabajo del contenedor - define el comando de arranque de los contenedores basados en esta imagen como
python ./server.py
Ya podemos construir nuestra imagen con el comando: docker build -t myimage .
Y una vez construida (ver con docker images
) podemos crear contenedores a partir de esta imagen:
|
|
Optimizando la construcción de imágenes Docker
- Imagen Base
-
Por supuesto conviene usar siempre imágenes oficiales
-
La imagen que escojamos como base determina muchas de las propiedades de la imagen final. Generalmente hay opciones para construir imágenes ligeras (casi siempre basadas en Alpine Linux) Para Python podemos buscar las imágenes oficiales de tipo slim, por ejemplo
python:3.10.9-slim
- Orden de instrucciones en el dockerfile
-
Para acelerar las operaciones de recontrucción de imágenes, que serán muy frecuentes durante el desarrollo, Docker implementa mecanismos de caché. Para aprovechar esta funcionalidad es muy importante que dejemos las opciones más estables (que tengan menos cambios a lo largo del desarrollo) al principio del dockerfile. Por ejemplo nuestro dockerfile de ejemplo pone al principio los comandos de instalación de dependencias y despues copia los fuentes. Como las dependencias no cambiarán tan frecuentemente como el código fuente de nuestro proyecto se podran aprovechar las imágenes de la caché.
- Construcción de imágenes por etapas
-
Esta técnica se usa más bien para preparar las imágenes para distribución, no en la fase de desarrollo. Por ejemplo veamos como contruir nuestra aplicación y preparar una imagen ligera para distribución:
|
|
Comprobar estas referencias y completar
Varios experimentos con interfaces de usuario
Tkinter
PySimpleGUI
NiceGUI
Textual
Miscelanea
Soluciones de exercism
Pistas para el ejercicio ‘matrix’
Una matriz o array en python se puede representar como una ’lista de listas’
Asi la matriz
1 2 3 4 5 6 7 8 9
Podría representarse como una lista de python que almacenase una lista por cada fila
|
|
El método clásico de transponer (que las filas se conviertan en columnas) una matriz en python era:
|
|
Que no es muy intuitivo ¬_¬
Pero en python moderno con las list comprehension podemos escribir:
|
|
Hemos supuesto que el array está “bien formado”, es decir que todas las filas tienen el mismo número de elementos, asi que para calcular cuantos elementos hay por fila nos vale la logitud de cualquier fila (lo calculamos con la fila cero)
La ‘comprehension’ externa recorre los índices de los elementos de una fila (serían los números de columna) y para cada número de columna devuelve otra ‘comprehension’ (que llamaremos interna)
La ‘comprehension’ interna devuelve una lista formada por el elemento i-ésimo de cada linea del array, (es decir, los elementos de la columna i-ésima.
en nuestro ejemplo el contenido de my_array_in_cols, al final sería
|
|
Jupyter (antes conocido como iPython)
Por descontado, hay que instalarlo en un virtualenv
|
|
En la sesión del curso instalamos tambien seaborn para ver gráficos:
|
|
Expresiones Regulares en Python
Un par de páginas web (hay muchísimas) para probar nuestras expresiones regulares
Un buen recurso para aprender expresiones regulares con varias versiones, entre ellas castellano
Un muy buen tutorial de expresiones regulares en python:
Algunas librerias y frameworks interesantes
argparse
|
|
- Toga https://toga.readthedocs.io/en/latest/ para hacer GUI (interfaces de usuario)
- Kivy https://kivy.org/#home Interfaces de usuario, dispositivos móviles
- Dash https://dash.plotly.com/ Para hacer cuadros de mandos, se basa en plotly que a su vez se basa en d3.js. Pese a la apariencia de la página web, es software libre con licencia MIT
Frameworks Web
Flask
El más simple de los frameworks, siempre es bueno dedicarle algún tiempo para ver los conceptos básicos. Se puede hacer cualquier aplicación web con Flask, pero los frameworks más potentes nos ahorrarán mucho trabajo.
Sigue siendo imbatible para aplicaciones sencillas
Un buen tutorial de Flask: El mega tutorial de Flask. Son 23 capitulos publicados en la web.
web2py
Un framework más potente que Flask y más sencillo que Django
El libro oficial de web2py (hay versión en español)
El capítulo 3 del libro es un buen punto de partida para autoformación
Un buen tutorial de web2py, son siete videos de unos 20 minutos cada uno:
-
Los videos de Maximo di Pierro (el creador de web2py) un curso de 30 videos super-completo Aseguraos de empezar por el primer video (hay que ir hacia atrás en el historial del usuario) El primero sería este
-
Una guia (sin terminar) que puede valer para instalar web2py es esta
celery
Una cola de tareas para Python.
Una cola de tareas sirve para distribuir el trabajo en threads (hilos de ejecución concurrente) o entre distintas máquinas.
Las entradas para la cola de tareas son unidades de trabajo denominadas tareas (tasks). Trabajadores (workers) dedicados monitorizan la cola constantemente y ejecutan las tareas encoladas.
Celery se comunica mediante mensajes, normalmente usando un broker que hace de mediador entre clientes y workers. Los clientes (clients) ofertan tareas enviando mensajes a la cola. El broker facilita que esos mensajes lleguen a los workers.
Así pues un sistema Celery se compone de múltiples workers y brokers, lo que permite obtener alta disponibilidad y sistemas fáciles de escalar horizontalmente.
Celery está escrito en Python pero se ha hecho tan popular que se puede usar desde varios lenguajes de programación.
Celery necesita un broker para funcionar, tanto RabittMQ como Redis ofrecen soluciones completamente funcionales pero Celery soporta muchos más.
Adicionalmente podemos instalar un sistema que actúe como almacén de resultados (results store). Celery soporta muchos diferentes.
Montando un escenario sencillo con Celery
Lanzamos un RabittMQ dockerizado:
|
|
Creamos nuestro entorno virtual como de costumbre e instalamos Celery
|
|
Creamos un fichero tasks.py
:
|
|
Con esto podríamos ya lanzar nuestro primer worker ejecutando el comando: celery -A tasks worker --loglevel=INFO
Esto nos vale para probar, en un entorno de producción nos interesa lanzar los workers como servicio (ver Daemonization)
Ahora podríamos abrir una sesión con el intérprete de Python y lanzar una tarea al worker con
|
|
Django
Como de costumber creamos un entorno virtual:
|
|
Creamos un directorio para las pruebas y le asignamos el virtualenv local.
|
|
Para empezar hacemos el tuto oficial
python -m django version
nos permite ver la versión de Django (la 4.0.5)django-admin startproject mysite
nos permite crear un nuevo directorio de proyecto con su estructura característicapython manage.py runserver
ejecuta el server, en nuestro caso vale con./manage.py runserver
python manage.py runserver 8000
ejecuta el server en el puerto 8000python manage.py runserver 0:8000
ejecuta el server en el puerto 8000 en todas las IP del servidorpython manage.py startapp polls
crea el directorio para la aplicaciónpolls
, las aplicaciones se crean todas en el mismo directorio donde reside elmanage.py
views en Django
Para crear una vista:
- definimos una función en el fichero
views.py
de nuestra aplicación - en el fichero
urls.py
de nuestra aplicación, asociamos la función a unpath
- en el fichero
urls.py
de nuestro site, tenemos que incluir el módulopolls.urls
que se corresponde con el ficheropolls/urls.py
, para hacer esto siempre usamosinclude
(from django.urls import include, path
)
La funcion path
tiene cuatro parámetros:
- route
-
es un string que contiene un patrón para urls. Cuando Django recibe una petición (request) Django recorrerá todos los patrones de la lista
urlpatterns
hasta encontrar una que encaje. Al hacer esta búsqueda se busca solo elpath
no se comprueba el dominio que aparece en la petición ni el tipo (GET
oPOST
) ni los parámetros. - view
-
cuando Django encuentra el patrón que encaja se invoca a la función view asociada a ese patrón, pasando el objeto HttpRequest y cualquier otro valor que haya sido capturado
- kwargs
-
se pueden pasar parámetros adicionales en un diccionario
- name
-
siempre es práctico asignar un nombre a las URL para poder referirnos a ellas desde cualquier parte
Establecer la base de datos
En el fichero mysite/settings.py
es un módulo de Python normal y corriente que almacena distintos valores de configuración de Django en variables.
Por defecto tenemos configurado usar SQLite3 como motor de base de datos. Si queremos usar otra de las bases de datos soportadas tenemos que instalar el backend correspondiente (ver doc)
Si usamos SQLite3 en el parámetro NAME
especificamos el fichero de la base de datos SQLite3
Una vez establecida la base de datos podemos empezar a definir nuestros modelos (models), básicamente son las tablas de la base de dawos con sus metadatos.
Los modelos se definen en el fichero polls/models.py
, cada tabla en la base de datos se corresponde con una clase en el fichero.
Cuando tenemos los modelos definidos necesitamos ejecutar dos pasos adicionales:
- Dar de alta nuestra app en el fichero
mysite/settings.py
- Activar los modelos, con la operación que en Django se denomina Migración. Las migraciones quedan codificadas en ficheros python en el directorio
migrations
de la aplicación correspondiente.
Comandos:
python manage.py makemigrations polls
prepara las migraciones y las deja listas para ejecutarse en el directoriomigrations
de la aplicación correspondiente.python manage.py sqlmigrate polls 0001
nos dice que comandos sql corresponden a la migración. Son los comandos que se ejecutarán en la base de datos cuando ejecutemos la migración.python manage.py check
hace comprobaciones sin ejecutar la aplicaciónpython manage.py migrate
ejecuta la migración (de hecho ejecuta todas las que haya pendientes)python manage.py shell
nos abre un shell para hacer experimentos
Django admin
python manage.py createsuperuser
nos permite crear un usuario administrador para nuestra instancia de Django, podemos acceder al interfaz de administración en la dirección http://127.0.0.1:8000/admin/
Para que nuestra applicación sea accesible desde el interfaz de administración de Django, es necesario modificar el fichero polls/admin.py
para que incluya las siguientes lineas:
|
|
Nuevas vistas
Para generar nuevas vistas:
- Definimos la nueva función en el fichero
polls/views.py
- Añadimos las nuevas url a los
urlpatterns
definidos en el ficheropolls/urls.py
Cada vista tiene que lograr uno de dos objetivos: o bien genera un HttpResponse válido o bien devuelve una excepción como por ejemplo Http404
A parte de eso la vista puede hacer todo tipo de cosas. Leer registros de una base de datos, generar ficheros de cualquier tipo, usar el sistema de Templates de Django, etc etc.
Bibliografía
- El libro de Ekaitz que hemos “seguido” en este curso
- La traducción al gallego del mismo libro, elaborada por asistentes al curso
- El libro del Dr. Chuck. Los cursos de este hombre en Coursera se podían seguir como oyente de forma gratuita y están muy bien para empezar. En todo caso aquí tenéis un libro suyo (disponible en castellano)
Batiburrillo de enlaces
- Pilulas para o teletraballo
- Maestro das traducións
- Portal das palabras
- Apertium translator
- Python with VCS
- Select venv with VCS
- Decoradores ref 1
- Decoradores ref 2
Para mais adiante:
Problemas instalando Kivy o Pygame:
- En esta página en el web oficial, parece que se detallan las dependencias de kivy.
- Para instalar pygame o kivy parece que hay dependencias con sdl2 En esta otra página explican como instalar pygame en python 3.8
No se vayan todavía…