Crear un CLI en Python con Click es más claro y mantenible cuando organizas bien tu proyecto, defines comandos con decoradores y configuras setup.py para instalar un ejecutable. Aquí tienes el esqueleto base: estructura de archivos, comandos create/list/update/delete y un flujo de instalación editable en un virtualenv.
¿Cómo organizar la estructura de archivos en Python para un CLI con Click?
Diseñar con múltiples archivos hace el código más legible y escalable. Un subdirectorio funciona como módulo en Python y agrupa responsabilidades específicas.
Un directorio raíz para el proyecto.
Un archivo de entrada: PV.py como punto de entrada del CLI.
Subdirectorios como módulos: agrupan funciones relacionadas.
Responsabilidad única por archivo: hace el mantenimiento más simple.
¿Qué comandos y decoradores definen el CLI de clientes?
Los decoradores de Click convierten funciones en comandos. Se usa @click.group() para declarar un grupo y @clients.command() para registrar subcomandos. Con @click.pass_context se recibe un contexto mutable; aquí se inicializa como diccionario literal vacío.
¿Cómo inicializar el contexto con click pass context?
En tu punto de entrada se importa Click, se define un group y se inicializa el objeto contexto:
# PV.pyimport click
@click.group()@click.pass_contextdefCLI(ctx):# inicializar el contexto como diccionario literal vacío ctx.obj ={}# registrar el grupo de clientes desde el módulo clients.commandsfrom clients import commands as clients_commands
CLI.add_command(clients_commands.all)
Puntos clave:
ctx.obj = {}: contexto listo para compartir datos entre comandos.
Legibilidad: se importa clients.commands como alias y se registra con add_command.
¿Cómo convertir funciones en comandos del grupo clients?
Define el grupo clients y sus comandos básicos. Los docstrings alimentan la ayuda de Click, es decir: la interfaz basada en texto del CLI.
# clients/commands.pyimport click
@click.group()defclients():"""Manages the client's life cycle."""pass# placeholder para evitar error@clients.command()@click.pass_contextdefcreate(ctx, name, company, email, position):"""Create a new client."""pass@clients.command("list")# evitar colisión con palabra reservada list@click.pass_contextdeflist_cmd(ctx):"""List all clients."""pass@clients.command()@click.pass_contextdefupdate(ctx, uid):"""Updates a client."""pass@clients.command()@click.pass_contextdefdelete(ctx, uid):"""Delete a client."""pass# alias para registrar todo el grupo desde PV.pyall= clients
Detalles importantes:
Decoradores: @clients.command() marca cada función como comando.
Docstrings como ayuda: Click los muestra en --help.
Convención de espacios: dos líneas en blanco entre funciones de nivel módulo.
Alias all: simplifica el registro del grupo completo.
¿Cómo instalar y ejecutar el comando con setup.py y un virtualenv?
La instalación convierte tu CLI en un ejecutable del sistema: sin invocar directamente al intérprete de Python. Se declara el nombre del comando, la versión y el entry point hacia CLI dentro de PV.py.
Ejemplo mínimo de setup.py:
# setup.pyfrom setuptools import setup
setup( name='PV',# nombre del comando instalado version='0.1',# versión semántica py_modules=['PV'],# módulo de entrada install_requires=['click',# dependencia principal], entry_points={'console_scripts':['PV=PV:CLI',# comando=modulo:funcion_de_entrada],},)
Instalar en modo editable dentro de un virtualenv permite ver cambios al instante:
# crear y activar el ambiente virtualvirtualenv -p python3 venv
source venv/bin/activate
# instalar en modo editablepip install --editable .# verificar e inspeccionar la ayudawhich PV
PV --help
PV clients --help
Qué observarás al usar --help:
Uso y opciones del comando raíz.
El grupo clients con su descripción: "Manages the client's life cycle".
Me desmotive bastante desde esta clase, creo que no se explica muchas con claridad, por lo que veo a muchos nos salieron errores que debieron ser validados previamente en la clase, la verdad es el curso que mas me ha decepcionado en lo que llevo de platzi. Creo que buscare profundizar en otro lado.
creo que como todo, hay cosas muy precisas que se deben escribir a mi me salio un error sin embargo revise a profundidad y tenia un par de errores typo como le dicen.
Creo que es normal este tipo de cosas la cuestión es tener paciencia y revisar. Si copia y pega el codigo de ejemplo no te enteras de cual fue el error. Por el contrario considero que la clase es muy buena y cada uno tenemos un ruta de aprendizaje diferente y claro es necesario profundizar y buscar por otro lado las cosas que en ocasiones no entendemos. Ahora bien en una clase pre grabada de 15 minutos nunca encontraras todas las respuestas. Con todo y ello las clases del profesor Aoresti son de las mejores que tiene Platzi
A mi este curso me parece fenomenal, te lleva desde lo más básico hasta cosas avanzadas para realmente aplicar lo aprendido y saltar a hacer cosas prácticas. ¿No te pareció increíble poder generar u propia línea de comandos? es algo que nunca pensé en hacer, pero estoy maravillado.
.
Ciertamente el curso requiere que además de dominar los conceptos de Python, también, que conozcas sobre la terminal. Por eso está bien que sea un curso intermedio. No te desanimes, haz una pausa y repasa clases anteriores así como conceptos que no entiendas y regresa.
.
Espero que hayas terminado el curso.
.
A un año de este comentario ¿Cómo vas con Python?
Al igual que en el curso básico de python cuando tratamos temas avanzados el curso va muy rápido y no nos muestran detalles, tampoco soluciones para los que estamos en windows, pero no voy a enfocar solo en las debilidades del curso ya que de verdad lo he disfrutado bastante, mi solución es utilizar el bash de Git y con el bash o linea de comandos dirigirse a la carpeta de Platzi-ventas, luego seguir estos pasos:
1- pip install virtualenv
2- python -m venv venv
Ahora ya tenemos creado el ambiente virtual, debemos activarlo:
Posicionados en la misma carpeta de Platzi-Ventas ingresamos en el dash el comando:
source venv/Scripts/activate
Ahora podemos seguir los pasos que el profe nos explica en el curso, esto lo encontre en el siguiente video:
Espero les funcione.
Me gusta el enfoque que le das a tu comentario, no te desesperas y buscas la forma de solucionarlo, además, compartes tu solución con los demas. Gracias.
Link please
Se perdio todo el manejo en este punto, veniamos lento en cosas basicas y luego cuando se va a algo un poco mas complejo, el instructor da por sentadas muchas cosas y pasa demasiado rapido. Seria bueno que leyeran los comentarios de los estudiantes, no soy el unico que sintio que se perdio la calidad.
¿Cómo te fue con el curso?
.
Se notó el cambio de ritmo, sin embargo, este curso repasó desde los conceptos básicos hasta más avanzados y eso me gustó bastante.
Creo que la calidad va en aumento, se aplica lo que se ha visto antes, no solo en el curso sino en otros anteriores que son básicos. A partir de este punto viene lo bueno y eso me emociona, poder aplicarlo en un ambiente fuera del intérprete de Python.
.
Creo que todos pasamos por momentos de frustración con los errores que salen o por falta de entendimiento, pero hay que ir a tomar aire y regresar.
.
¡Ánimo!
.
¿Terminaste el curso?¿Qué te llevaste al final?
-----ENTORNO VIRTUAL EN WINDOWS----
luego seguí estos pasos. 1. pip Install virtualenv 2. Pip Install virtualenvwrapper-win:
**3. ** una vez echo esto anote el comando que dice el profe con una ligera modificación
estando en la carpeta “platzi-ventas” ejecuto el comando:
• virtualenv --python=python venv
si ya ha respondido la consola con done, ingreso a la carpeta con el nombre que se creo** “venv”**
• **cd ** venv/Scripts
ejecuto el archivo activate
activate, inmediatamente inicializa el ambiente virtual tal como al profe!! EJ:
… \CURSO PLATZI\CURSO_PYTHON_3\PLATZI-VENTAS\venv\Script> activate
Y por fin ingresas al entorno virtual
(venv) C:\Users…\CURSO PLATZI\CURSO_PYTHON_3\PLATZI-VENTAS\venv
luego regresa a la carpeta donde esta es en la Carpeta PLATZI-VENTAS y ejecuta : pip install --editable .
muchas gracias no olvidar: pip install --editable .
inlcuido el espacio despues de editable y el punto
me salvaste la vida
Un millon de errores, hasta este punto no pude solucionar nada a pesar de haber tomado un curso previo de python. Como raro todos los cursos de platzi son a la carrera y bastante incompletos en sus partes mas complejas.
x2
Si tuvieron algun error con virtualenv y estan usando windows esto me sirvio.
ni si quiera explican bien para que funciona el framework click, que sentido tiene?
HOLA! AL FINAL DESPUES DE COMO PUDIERON VER TODAS LAS PREGUNTAS QUE HICE, LES DEJO MI SOLUCIÓN! PARA TODOS LOS QUE ESTÁN EN
¡¡WINDOWS 10!!
0)Abrir la consola(cmd), y entrar a la carpeta que contiene todos
los archivos y subdirectorios
1)python -m virtualenv <nombre del entorno>
2)venv\Scripts\activate.bat
3)pip install --editable .
4)where pv
Muchas gracias por la información. :)
Si al poner el comando python -m virtualenv venv le da un error: No module named virtualenv, esto quiere decir que tu versión de python no tiene instalado virtualenv asi que estando en Windows necesitarán bajarse los paquetes usando pip install virtualenv y después volver a lanzar el comando que dio error.
Para quien presente errores
Verifica que tengas instalado virtualenv .
1)si no lo tienes usa pip3 install virtualenv
2.Verifica que tengas creado y activado el ambiente virtual
2.1) virtualenv nombre_entorno -p python3
Para activarlo
2.2)source nombre_entorno/bin/activate(para ubuntu)
2.3) \env\Scripts\activate.bat(para windows)
3.Dirigete a la carpeta donde tengas los archivos creados en la clase.
ejecuta el codigo pip3 install --editable
4.1)Debes tener instalado Click, si no es así ingresa pip3
install click
5.Por ultimo y no menos importante, verifica que tu dirección de directorio no tenga espacios
/mnt/d/python/CRUD platzi/platzi ventas (esto esta mal)
/mnt/d/python/CRUD_platzi/platzi_ventas(Asi debe estar)
Solo cambia el nombre de esas carpetas y quitales los espacio
O saldra este error: bad interpreter: No such file or directory
intento instalar pero pip o pip3 no lo reconoce como un comando
No es el mejor tema que se trató de éste curso, no se entendió nada. Está todo bien con buscar y revisar en otros sitios para ampliar más los temas, pero al menos los conceptos deberían quedar claros o que al menos se sepa que es lo que se quiere hacer.
Cierto, este curso no es para alguien que va comenzando, igualmente creo que debimos ver que hay debajo del cofre de CLICK para comprender qué estamos usando, aunque sea un poco más
Para los que no tienen tree en su sitema: sudo apt-get install tree
Esto está buenísimo. Gracias! :D
Muchas gracias!!!
En windows si no tienen virtual env
# pip install virtualenv
# python -m venv env
# .\env\Scripts\activate.bat# .\env\Scripts\activate
# deactivate(este es para salir)
El profesor da por hecho que tenemos mac y pone puntos y cosas que solo se utilizan en mac, ¿pero los de windows qué? Aparte ya tomé el curso anterior de python y fue exactamente igual y al llegar a este punto de ambiente virtual todo se complicó y avanza muy rápido como si supiésemos ya todo.
Hola, te lo digo en buena, no creo que sea por mac, los comandos que utiliza son de entorno Unix, sea linux o mac, en windows puedes instalarte algunas herramientas que te ayudaran a utilizar estos comandos o cosas que no entiendes, pero mi mejor recomendación si te dedicaras a la programación es que uses Linux, y si tienes la oportunidad una Mac, cuando ya domines el entorno Unix.
Saludos y éxitos.
Instalen esto primero,
pip3 install virtualenv
sino les saldra un error al hacer
virtualenv --python=python3 venv
gracias
Me parece que no quedo muy claro el uso de click o al menos para mi no lo fue.
Click es un paquete de Python para crear "bonitas" interfaces de línea de comandos de una manera componible con tan poco código como sea necesario. Es el "Kit de creación de interfaz de línea de comandos". Es altamente configurable pero viene con valores predeterminados sensibles listos para usar.
Supongo que si no se utilizara, trabajar con la linea de comandos seria mas engorroso. Es lo que yo creo.
Mi corazón esta escrito en C así que quería usar un framework al que le tengo mucho cariño el cual es Qt por suerte es casi universal y funciona con Python
Bien el ejercicio de la lista de clientes lo hice con una interfaz grafica, me gusto como se ve :D si quiere puedes ver mi código y jugar con el, esta en mi github
aqui esta el codigo para consola:
--sin click-- XD
import sys
import os
CLIENTES=[]MENU_DICCIONARIO={'N':'NOMBRE','P':'POSICION','C':'COMPANIA','E':'EMAIL'}BASE_TXT='./lista_de_clientes.txt'BASE_TEMP='lista_de_clientes.temp'def AbrirBase_Declientes(): global BASE_TXT,CLIENTEStry:withopen(BASE_TXT,'r',encoding='utf-8')as__ARCHIVO__: base_de_clientes = __ARCHIVO__.read() limite =0 un_cliente =dict() un_dato_del_cliente = base_de_clientes.split(',')for index, dato inenumerate(un_dato_del_cliente):if index %2!=0: un_cliente[un_dato_del_cliente[index -1]]= dato
limite +=1if limite ==4:CLIENTES.append(un_cliente) un_cliente =dict() limite =0 except FileNotFoundError:withopen(BASE_TXT,'w',encoding='utf-8')as__ARCHIVO__:returndef GuardarBase_DeClientes(): global BASE_TXT,CLIENTESwithopen('lista_de_clientes.temp','w', encoding='utf-8')as__ARCHIVO__:for cliente inCLIENTES:for llave, valor in cliente.items(): __ARCHIVO__.write(f'{llave},{valor},') os.remove(BASE_TXT) os.rename(BASE_TEMP,BASE_TXT)def Agrega_Cliente(): global CLIENTES cliente =dict()print('por favor agrega:')for valor inMENU_DICCIONARIO.values(): cliente[valor]=input(f'{valor} :')CLIENTES.append(cliente)Mostrar_Clientes()GuardarBase_DeClientes()def Elimina_Cliente():print('Como desea localizar a su cliente a eliminar: ') cliente =busqueda_de_cliente()ifcliente: accion =__Dame_comando(texto ='deseas continuar [S]i / [TECLA] no : ')if accion =='S': indice = cliente[0]iflen(cliente)>1: indice =__Dame_comando(cliente,'Elige el indice de quien deseas eliminar : ')CLIENTES.pop(indice)GuardarBase_DeClientes()def Actualiza_Cliente():print('Localize su cliente para actualizar: ') cliente =busqueda_de_cliente()ifcliente: accion =__Dame_comando(texto ="deseas hacer una actualizacion [S]i / [TECLA] no : ") indice =-1while accion =='S':if indice ==-1 and len(cliente)==1: indice = cliente[0] elif indice ==-1: indice =__Dame_comando(cliente,"Elige el indice de quien deseas actualizar : ") llave =__Dame_comando(MENU_DICCIONARIO,'que deseas actualizar :')CLIENTES[indice][llave]=input(f'actualiza {llave} : ')print('¿Quieres continuar ACTUALIZANDO a')Mostrar_Clientes([indice])GuardarBase_DeClientes() accion =__Dame_comando(texto='[S]i /[TECLA] no : ')def busqueda_de_cliente(): llave =__Dame_comando(MENU_DICCIONARIO,'Buscar por: ') valor =input(f'ingresa el {llave} : ')returnBusca_Cliente(llave,valor,CLIENTES)def Busca_Cliente(llave,valor,lista_de_diccionarios):print(f'{llave} : {valor}') cliente_localizado =[] cliente_localizado =__localiza_por_medio_de(llave,valor,lista_de_diccionarios)ifcliente_localizado:print('mostrando informacion: ')Mostrar_Clientes(cliente_localizado)else:print('el cliente no ha sido localizado')return cliente_localizado
def __localiza_por_medio_de(llave,valor,lista_de_diccionarios): objeto = valor.lower() indice =[]for i , cliente inenumerate(lista_de_diccionarios):if cliente[llave]== objeto: indice.append(i)return indice
def Mostrar_Clientes(indice =None): global CLIENTESif indice ==None:for ind, cliente inenumerate(CLIENTES):print(f'[{ind}] : ',end='')for llave, valor in cliente.items():print(f'[{llave} = {valor}]', end=' ')print("")else:for i inindice:print(f'[{i}] : ',end='')for llave, valor inCLIENTES[i].items():print(f'[{llave} = {valor}]',end=' ')print('')MENU='''
BIENVENIDO******************** ¿Que desea realizar?[I]ngresar cliente
[B]uscar cliente
[E]liminar cliente
[A]ctualizar cliente
[M]ostrar clientes
[TECLA] para salir
'''
def Interfaz():AbrirBase_Declientes()whileTrue:print('') comando =__Dame_comando(texto=MENU)if comando =='I':Agrega_Cliente() elif comando =='B':busqueda_de_cliente() elif comando =='E':Elimina_Cliente() elif comando =='A':Actualiza_Cliente() elif comando =='M':Mostrar_Clientes()else:breakdef __Dame_comando(menu_de_intercion =None, texto =''):whileTrue:print(texto)iftype(menu_de_intercion)== dict:for llave , valor in menu_de_intercion.items():print(f'[{llave}] : [{valor}] ') comando =input().upper()iftype(menu_de_intercion)== dict:try:return menu_de_intercion[comando] except KeyError: pass
elif menu_de_intercion ==None:iflen(comando)==1:return comando.upper() elif type(menu_de_intercion)== list:try:ifint(comando)inmenu_de_intercion:returnint(comando) except ValueError: pass
print('intentalo de nuevo ')if __name__ =="__main__":Interfaz()```
Esta clase hubiera sido mejor si se dividia en mas, para aprovechar de explicar todo con detalle, o hubieran dejado algo de documentacion para leer. Ni modo tocara googlear.
Ibamos muy bien, pero esta clase no me gusto mucho
¡Hola @MDCMC! ¿Puedo ayudarte con algo? ¿Hay cierta parte en específico que no entendiste? Te dejo el link de la documentación oficial de click --> https://click.palletsprojects.com/en/7.x/
Estos temas mas complejos tendrían que desarrollarse en 2 o 3 clases mínimo... No vale la pena así. Sirve poco y nada esto. Nadie viene sin saber este tema y termina teniendolo claro despues de esta clase. Es preferible leer documentación de Python y consultar con google.
Así con videitos de 15 minutos, superficiales, Platzi no tiene sentido. Youtube es gratis y mucho mejor que esto.
¡Hola Julián! Gracias por tu feedback, quiero que sepas que la actualización del Curso de Python no va a tener estos errores, el equipo está trabajando muy duro para darte la mejor experiencia 💪🏼