programas - ¿Cuál es la mejor estructura de proyecto para una aplicación Python?
estructura basica de python (8)
Imagine que desea desarrollar una aplicación de escritorio de usuario final (no web) no trivial en Python. ¿Cuál es la mejor manera de estructurar la jerarquía de carpetas del proyecto?
Las características deseables son la facilidad de mantenimiento, la compatibilidad con IDE, la idoneidad para el bifurcado / fusión de control de fuente y la fácil generación de paquetes de instalación.
En particular:
- ¿Dónde pones la fuente?
- ¿Dónde pones guiones de inicio de aplicación?
- ¿Dónde pones el proyecto IDE cruft?
- ¿Dónde pones las pruebas de unidad / aceptación?
- ¿Dónde coloca los datos que no son de Python, como los archivos de configuración?
- ¿Dónde coloca fuentes que no sean de Python, como C ++ para los módulos de extensión binaria pyd / so?
De acuerdo con la estructura del sistema de archivos de un proyecto Python de Jean-Paul Calderone:
Project/
|-- bin/
| |-- project
|
|-- project/
| |-- test/
| | |-- __init__.py
| | |-- test_main.py
| |
| |-- __init__.py
| |-- main.py
|
|-- setup.py
|-- README
Echa un vistazo a Open Sourcing a Python Project de la manera correcta .
Permítanme un extracto de la parte del diseño del proyecto de ese excelente artículo:
Al configurar un proyecto, el diseño (o estructura de directorios) es importante para hacerlo bien. Un diseño sensato significa que los contribuyentes potenciales no tienen que gastar eternamente buscando un trozo de código; Las ubicaciones de los archivos son intuitivas. Ya que estamos tratando con un proyecto existente, significa que probablemente deba mover algunas cosas.
Empecemos por la parte superior. La mayoría de los proyectos tienen una serie de archivos de alto nivel (como setup.py, README.md, Requirements.txt, etc.). Luego hay tres directorios que cada proyecto debería tener:
- Un directorio de documentos que contiene la documentación del proyecto.
- Un directorio nombrado con el nombre del proyecto que almacena el paquete real de Python
- Un directorio de prueba en uno de dos lugares.
- Bajo el directorio del paquete que contiene el código de prueba y los recursos
- Como un directorio autónomo de nivel superior Para tener una mejor idea de cómo deben organizarse sus archivos, aquí hay una instantánea simplificada del diseño de uno de mis proyectos, Sandman:
$ pwd
~/code/sandman
$ tree
.
|- LICENSE
|- README.md
|- TODO.md
|- docs
| |-- conf.py
| |-- generated
| |-- index.rst
| |-- installation.rst
| |-- modules.rst
| |-- quickstart.rst
| |-- sandman.rst
|- requirements.txt
|- sandman
| |-- __init__.py
| |-- exception.py
| |-- model.py
| |-- sandman.py
| |-- test
| |-- models.py
| |-- test_sandman.py
|- setup.py
Como puede ver, hay algunos archivos de nivel superior, un directorio docs (generado es un directorio vacío donde sphinx colocará la documentación generada), un directorio sandman y un directorio de prueba debajo de sandman.
En mi experiencia, es sólo una cuestión de iteración. Ponga sus datos y código donde crea que vayan. Lo más probable es que, de todos modos, te equivocarás. Pero una vez que tenga una mejor idea de cómo se van a dar las cosas, estará en una mejor posición para hacer este tipo de conjeturas.
En cuanto a las fuentes de extensión, tenemos un directorio de código debajo del tronco que contiene un directorio para python y un directorio para varios otros idiomas. Personalmente, estoy más inclinado a intentar colocar cualquier código de extensión en su propio repositorio la próxima vez.
Con eso dicho, vuelvo a mi punto inicial: no le dé demasiada importancia. Ponlo en algún lugar que parezca funcionar para ti. Si encuentra algo que no funciona, puede (y debería) cambiarse.
Esta publicación de blog de Jean-Paul Calderone se da comúnmente como una respuesta en #python en Freenode.
Estructura del sistema de archivos de un proyecto Python
Hacer:
- Nombre el directorio algo relacionado con su proyecto. Por ejemplo, si su proyecto se llama "Twisted", nombre el directorio de nivel superior para sus archivos de origen
Twisted
. Cuando realices lanzamientos, debes incluir un sufijo de número de versión:Twisted-2.5
.- cree un directorio
Twisted/bin
y ponga sus ejecutables allí, si tiene alguno. No les dé una extensión.py
, incluso si son archivos de origen Python. No coloque ningún código en ellos excepto una importación y una llamada a una función principal definida en algún otro lugar de sus proyectos. (Arruga leve: ya que en Windows, el intérprete es seleccionado por la extensión de archivo, sus usuarios de Windows realmente quieren la extensión .py. Entonces, cuando empaqueta para Windows, puede agregarlo. Desafortunadamente, no hay un truco fácil de distutils que Sé de automatizar este proceso. Teniendo en cuenta que en POSIX la extensión .py es solo una verruga, mientras que en Windows la falta es un error real, si su base de usuarios incluye usuarios de Windows, puede optar por tener solo el .py extensión a todas partes.)- Si su proyecto se puede expresar como un único archivo fuente de Python, colóquelo en el directorio y asígnele un nombre relacionado con su proyecto. Por ejemplo,
Twisted/twisted.py
. Si necesita varios archivos de origen, cree un paquete en su lugar (Twisted/twisted/
, con unTwisted/twisted/__init__.py
) y coloque sus archivos de origen en él. Por ejemplo,Twisted/twisted/internet.py
.- ponga sus pruebas de unidad en un subpaquete de su paquete (nota: esto significa que la única opción de archivo fuente de Python anterior fue un truco; siempre necesita al menos otro archivo para sus pruebas de unidad). Por ejemplo,
Twisted/twisted/test/
. Por supuesto, haz que sea un paquete conTwisted/twisted/test/__init__.py
. Coloque las pruebas en archivos comoTwisted/twisted/test/test_internet.py
.- agregue
Twisted/README
yTwisted/setup.py
para explicar e instalar su software, respectivamente, si se siente bien.No hagas
- ponga su fuente en un directorio llamado
src
olib
. Esto hace que sea difícil de ejecutar sin instalar.- ponga sus pruebas fuera de su paquete de Python. Esto hace que sea difícil ejecutar las pruebas en una versión instalada.
- cree un paquete que solo tenga un
__init__.py
y luego coloque todo su código en__init__.py
. Simplemente haga un módulo en lugar de un paquete, es más simple.- intente crear hacks mágicos para que Python pueda importar su módulo o paquete sin que el usuario agregue el directorio que lo contiene a su ruta de importación (ya sea a través de PYTHONPATH o algún otro mecanismo). No manejará correctamente todos los casos y los usuarios se enojarán con usted cuando su software no funcione en su entorno.
Intente iniciar el proyecto utilizando la plantilla python_boilerplate . En gran medida, sigue las mejores prácticas (p. Ej., Las de aquí ), pero es más adecuado en caso de que esté dispuesto a dividir su proyecto en más de un huevo en algún momento (y créame, con cualquier cosa que no sean los proyectos más simples, lo hará. situación común es cuando tiene que usar una versión modificada localmente de la biblioteca de otra persona).
¿Dónde pones la fuente?
- Para proyectos decentemente grandes tiene sentido dividir la fuente en varios huevos. Cada huevo iría como un setuptools-layout separado bajo
PROJECT_ROOT/src/<egg_name>
.
- Para proyectos decentemente grandes tiene sentido dividir la fuente en varios huevos. Cada huevo iría como un setuptools-layout separado bajo
¿Dónde pones guiones de inicio de aplicación?
- La opción ideal es tener el script de inicio de la aplicación registrado como un punto de
entry_point
en uno de los huevos.
- La opción ideal es tener el script de inicio de la aplicación registrado como un punto de
¿Dónde pones el proyecto IDE cruft?
- Depende del IDE. Muchos de ellos mantienen sus cosas en
PROJECT_ROOT/.<something>
en la raíz del proyecto, y esto está bien.
- Depende del IDE. Muchos de ellos mantienen sus cosas en
¿Dónde pones las pruebas de unidad / aceptación?
- Cada huevo tiene un conjunto separado de pruebas, que se guardan en su directorio
PROJECT_ROOT/src/<egg_name>/tests
. Personalmente prefiero usarpy.test
para ejecutarlos.
- Cada huevo tiene un conjunto separado de pruebas, que se guardan en su directorio
¿Dónde coloca los datos que no son de Python, como los archivos de configuración?
- Depende. Puede haber diferentes tipos de datos que no sean de Python.
- "Recursos" , es decir, datos que deben empaquetarse dentro de un huevo. Estos datos entran en el directorio de huevo correspondiente, en algún lugar dentro del espacio de nombres del paquete. Se puede utilizar a través del paquete
pkg_resources
. - "Archivos de configuración" , es decir, archivos que no son de Python que deben considerarse externos a los archivos de origen del proyecto, pero que deben inicializarse con algunos valores cuando la aplicación comienza a ejecutarse. Durante el desarrollo, prefiero mantener estos archivos en
PROJECT_ROOT/config
. Para la implementación puede haber varias opciones. En Windows se puede usar%APP_DATA%/<app-name>/config
, en Linux,/etc/<app-name>
o/opt/<app-name>/config
. - Archivos generados , es decir, archivos que pueden ser creados o modificados por la aplicación durante la ejecución. Preferiría mantenerlos en
PROJECT_ROOT/var
durante el desarrollo y bajo/var
durante la implementación de Linux.
- "Recursos" , es decir, datos que deben empaquetarse dentro de un huevo. Estos datos entran en el directorio de huevo correspondiente, en algún lugar dentro del espacio de nombres del paquete. Se puede utilizar a través del paquete
- Depende. Puede haber diferentes tipos de datos que no sean de Python.
- ¿Dónde coloca fuentes que no sean de Python, como C ++ para los módulos de extensión binaria pyd / so?
- En
PROJECT_ROOT/src/<egg_name>/native
- En
La documentación normalmente iría a PROJECT_ROOT/doc
o PROJECT_ROOT/src/<egg_name>/doc
(esto depende de si considera que algunos de los huevos son proyectos grandes separados). Algunas configuraciones adicionales estarán en archivos como PROJECT_ROOT/buildout.cfg
y PROJECT_ROOT/setup.cfg
.
La "Autoridad de Empaque de Python" tiene un proyecto de muestra:
https://github.com/pypa/sampleproject
Es un proyecto de muestra que existe como una ayuda para el Tutorial de Empaquetado y Distribución de Proyectos de la Guía del Usuario de Python Packaging.
Los datos que no son de Python se combinan mejor dentro de sus módulos de Python utilizando el soporte setuptools en setuptools . Una cosa que recomiendo encarecidamente es usar paquetes de espacio de nombres para crear espacios de nombres compartidos que puedan usar múltiples proyectos, como la convención de Java de poner paquetes en com.yourcompany.yourproject
(y poder tener un espacio de nombres com.yourcompany.utils
).
Re ramificación y fusión, si utiliza un sistema de control de fuente suficientemente bueno, manejará las combinaciones incluso a través de renombramientos; Bazaar es particularmente bueno en esto.
Al contrario de algunas otras respuestas aquí, tengo +1 en tener un directorio src
de nivel superior (con test
directorios doc
y test
lado). Las convenciones específicas para los árboles de directorios de documentación variarán según lo que esté usando; Sphinx , por ejemplo, tiene sus propias convenciones que admite su herramienta de inicio rápido.
Por favor, aproveche setuptools y pkg_resources; esto hace que sea mucho más fácil para otros proyectos confiar en versiones específicas de su código (y para que varias versiones se instalen simultáneamente con diferentes archivos sin código, si está usando package_data
).
No importa demasiado. Lo que te haga feliz funcionará. No hay muchas reglas tontas porque los proyectos de Python pueden ser simples.
-
/scripts
o/bin
para ese tipo de cosas de la interfaz de línea de comandos -
/tests
para tus pruebas -
/lib
para tus bibliotecas en lenguaje C -
/doc
para la mayoría de la documentación -
/apidoc
para los documentos API generados por Epydoc.
Y el directorio de nivel superior puede contener README''s, Config''s y otras cosas.
La elección difícil es si usar o no un árbol /src
. Python no tiene una distinción entre /src
, /lib
y /bin
como Java o C tiene.
Como algunos consideran que un directorio de nivel superior /src
tiene sentido, su directorio de nivel superior puede ser la arquitectura de nivel superior de su aplicación.
-
/foo
-
/bar
-
/baz
Recomiendo poner todo esto en el directorio "nombre de mi producto". Por lo tanto, si está escribiendo una aplicación llamada quux
, el directorio que contiene todas estas cosas se llama /quux
.
El PYTHONPATH
otro proyecto, entonces, puede incluir /path/to/quux/foo
para reutilizar el módulo QUUX.foo
.
En mi caso, ya que uso Komodo Edit, mi mazo IDE es un solo archivo .KPF. De hecho, puse eso en el directorio de nivel superior /quux
, y /quux
agregarlo a SVN.