tutorial librerias instalar for descargar python python-2.7 import pycharm packages

python - librerias - pycharm pip install



¿Cómo se organiza un proyecto python que contiene múltiples paquetes para que cada archivo en un paquete se pueda ejecutar de forma individual? (3)

TL; DR

Aquí hay un repositorio de ejemplo que se configura como se describe en el primer diagrama (a continuación): https://github.com/Poddster/package_problems

Si pudiera hacer que se vea como el segundo diagrama en términos de organización del proyecto y todavía puede ejecutar los siguientes comandos, entonces ha respondido la pregunta:

$ git clone https://github.com/Poddster/package_problems.git $ cd package_problems <do your magic here> $ nosetests $ ./my_tool/my_tool.py $ ./my_tool/t.py $ ./my_tool/d.py (or for the above commands, $ cd ./my_tool/ && ./my_tool.py is also acceptable)

Alternativamente: Dame una estructura de proyecto diferente que me permita agrupar archivos relacionados (''paquete''), ejecutar todos los archivos individualmente, importar los archivos a otros archivos en el mismo paquete e importar los paquetes / archivos a otros archivos del paquete .

Situación actual

Tengo un montón de archivos de Python. La mayoría de ellos son útiles cuando se pueden llamar desde la línea de comandos, es decir, todos usan argparse y if __name__ == "__main__" para hacer cosas útiles.

Actualmente tengo esta estructura de directorios, y todo está funcionando bien:

. ├── config.txt ├── docs/ │   ├── ... ├── my_tool.py ├── a.py ├── b.py ├── c.py ├── d.py ├── e.py ├── README.md ├── tests │   ├── __init__.py │   ├── a.py │   ├── b.py │   ├── c.py │   ├── d.py │   └── e.py └── resources ├── ...

Algunos de los scripts import cosas de otros scripts para hacer su trabajo. Pero ningún script es meramente una biblioteca, todos son invokables. por ejemplo, podría invocar ./my_tool.py , ./a.by , ./b.py , ./c.py etc. y harían cosas útiles para el usuario.

"my_tool.py" es el script principal que aprovecha todos los otros scripts.

Lo que quiero que suceda

Sin embargo, quiero cambiar la forma en que se organiza el proyecto. El proyecto en sí representa un programa completo utilizable por el usuario, y se distribuirá como tal, pero sé que partes de él serán útiles en diferentes proyectos más adelante, así que quiero intentar y encapsular los archivos actuales en un paquete. En el futuro inmediato también agregaré otros paquetes a este mismo proyecto.

Para facilitar esto, he decidido reorganizar el proyecto a algo como lo siguiente:

. ├── config.txt ├── docs/ │   ├── ... ├── my_tool │   ├── __init__.py │   ├── my_tool.py │   ├── a.py │   ├── b.py │   ├── c.py │   ├── d.py │   ├── e.py │   └── tests │   ├── __init__.py │   ├── a.py │     ├── b.py │   ├── c.py │   ├── d.py │   └── e.py ├── package2 │   ├── __init__.py │   ├── my_second_package.py | ├── ... ├── README.md └── resources ├── ...

Sin embargo, no puedo encontrar una organización de proyecto que satisfaga los siguientes criterios:

  1. Todos los scripts son invokables en la línea de comando (ya sea como my_tool/a.py o cd my_tool && a.py )
  2. Las pruebas realmente se ejecutan :)
  3. Los archivos del paquete2 pueden import my_tool

El problema principal es con las declaraciones de importación utilizadas por los paquetes y las pruebas.

Actualmente, todos los paquetes, incluidas las pruebas, simplemente import <module> y se resuelven correctamente. Pero cuando se enfrentan las cosas no funciona.

Tenga en cuenta que la compatibilidad con py2.7 es un requisito, por lo que todos los archivos tienen from __future__ import absolute_import, ... en la parte superior.

Lo que he intentado y los resultados desastrosos

1

Si muevo los archivos como se muestra arriba, pero dejo todas las declaraciones de importación como están actualmente:

  1. $ ./my_tool/*.py funciona y todos funcionan correctamente
  2. $ nosetests ejecutados desde el directorio superior no funciona. Las pruebas no pueden importar las secuencias de comandos de los paquetes.
  3. pycharm resalta las declaraciones de importación en rojo al editar esos archivos :(

2

Si luego cambio los scripts de prueba para hacer:

from my_tool import x

  1. $ ./my_tool/*.py aún funciona y todos funcionan correctamente
  2. $ nosetests ejecutados desde el directorio superior no funciona. Entonces, las pruebas pueden importar los scripts correctos, pero las importaciones en los scripts mismos fallan cuando los scripts de prueba los importan.
  3. pycharm resalta las declaraciones de importación en rojo en los guiones principales aún :(

3

Si mantengo la misma estructura y cambio todo para que sea from my_tool import entonces:

  1. $ ./my_tool/*.py resulta en ImportError s
  2. $ nosetests ejecuta todo bien.
  3. pycharm no se queja de nada

por ej. de 1 .:

Traceback (most recent call last): File "./my_tool/a.py", line 34, in <module> from my_tool import b ImportError: cannot import name b

4

También lo intenté from . import x from . import x pero eso solo termina con ValueError: Attempted relative import in non-package para la ejecución directa de scripts.

Mirando algunas otras respuestas SO:

No puedo usar python -m pkg.tests.core_test como

a) No tengo el .py principal ¿Supongo que podría tener uno?
b) ¿Quiero poder ejecutar todos los scripts, no solo main?

He intentado:

if __name__ == ''__main__'' and __package__ is None: from os import sys, path sys.path.append(path.dirname(path.dirname(path.abspath(__file__))))

pero no ayudó.

También probé:

__package__ = "my_tool" from . import b

Pero recibido:

SystemError: Parent module ''loading_tool'' not loaded, cannot perform relative import

añadiendo import my_tool before from . import b from . import b simplemente termina de nuevo con ImportError: cannot import name b

¿Fijar?

¿Cuál es el conjunto correcto de conjuros mágicos y el diseño del directorio para hacer que todo esto funcione?


Punto 1

Creo que está funcionando, entonces no lo comento.

Punto 2

Siempre utilicé pruebas al mismo nivel que my_tool, no debajo, pero deberían funcionar si haces esto en la parte superior de cada archivo de prueba (antes de importar my_tool o cualquier otro archivo py en el mismo directorio)

import os import sys sys.path.insert(0, os.path.abspath(__file__).rsplit(os.sep, 2)[0])

Punto 3

En my_second_package.py haga esto en la parte superior (antes de importar my_tool)

import os import sys sys.path.insert(0, os.path.abspath(__file__).rsplit(os.sep, 2)[0] + os.sep + ''my_tool'')

Atentamente,

JM


Para ejecutarlo desde ambas líneas de comando y actuar como biblioteca, al tiempo que permite que nosetest opere de manera estándar, creo que tendrá que hacer un doble enfoque en Importaciones.

Por ejemplo, los archivos Python requerirán:

try: import f except ImportError: import tools.f as f

Pasé e hice un PR del github que vinculó con todos los casos de prueba funcionando.

https://github.com/Poddster/package_problems/pull/1

Editar: Olvidé las importaciones en __init__.py para __init__.py correctamente en otros paquetes, agregó. Ahora debería poder hacer:

import tools tools.c.do_something()


Una vez que se mueve a la configuración deseada, las importaciones absolutas que está utilizando para cargar los módulos que son específicos de my_tool ya no funcionan.

Necesita tres modificaciones después de crear el subdirectorio my_tool y mover los archivos en él:

  1. Crea my_tool/__init__.py . (Parece que ya lo hace, pero quería mencionarlo para completarlo).

  2. En los archivos directamente debajo de my_tool : cambie las instrucciones de import para cargar los módulos del paquete actual. Entonces, en my_tool.py cambio:

    import c import d import k import s

    a:

    from . import c from . import d from . import k from . import s

    Necesita hacer un cambio similar a todos sus otros archivos. (Menciona haber intentado establecer __package__ y luego hacer una importación relativa, pero no es necesario configurar __package__ ).

  3. En los archivos ubicados en my_tool/tests : cambie las instrucciones de import que importan el código que desea probar a las importaciones relativas que se cargan desde un paquete en la jerarquía. Entonces, en test_my_tool.py cambiar:

    import my_tool

    a:

    from .. import my_tool

    Del mismo modo para todos los otros archivos de prueba.

Con las modificaciones anteriores, puedo ejecutar módulos directamente:

$ python -m my_tool.my_tool C! D! F! V! K! T! S! my_tool! my_tool main! |main tool!||detected||tar edit!||installed||keys||LOL||ssl connect||parse ASN.1||config| $ python -m my_tool.k F! V! K! K main! |keys||LOL||ssl connect||parse ASN.1|

y puedo ejecutar pruebas:

$ nosetests ........ ---------------------------------------------------------------------- Ran 8 tests in 0.006s OK

Tenga en cuenta que puedo ejecutar lo anterior tanto con Python 2.7 como con Python 3.

En lugar de hacer que los diversos módulos de my_tool sean ejecutables directamente, sugiero usar un archivo setup.py adecuado para declarar los puntos de entrada y dejar que setup.py cree estos puntos de entrada cuando se instale el paquete. Como tiene la intención de distribuir este código, debe usar setup.py para empaquetarlo formalmente de todos modos.

  1. Modifique los módulos que se pueden invocar desde la línea de comandos para que, tomando my_tool/my_tool.py como ejemplo, en lugar de esto:

    if __name__ == "__main__": print("my_tool main!") print(do_something())

    Tienes:

    def main(): print("my_tool main!") print(do_something()) if __name__ == "__main__": main()

  2. Cree un archivo setup.py que contenga los entry_points correctos. Por ejemplo:

    from setuptools import setup, find_packages setup( name="my_tool", version="0.1.0", packages=find_packages(), entry_points={ ''console_scripts'': [ ''my_tool = my_tool.my_tool:main'' ], }, author="", author_email="", description="Does stuff.", license="MIT", keywords=[], url="", classifiers=[ ], )

    El archivo anterior indica a setup.py que cree un script llamado my_tool que invocará el método main en el módulo my_tool.my_tool . En mi sistema, una vez que el paquete está instalado, hay un script ubicado en /usr/local/bin/my_tool que invoca el método main en my_tool.my_tool . Produce el mismo resultado que ejecutar python -m my_tool.my_tool , que he mostrado anteriormente.