No puedo importar mis propios módulos en Python

141

Me cuesta entender cómo funciona la importación de módulos en Python (nunca antes lo había hecho en ningún otro idioma).

Digamos que tengo:

myapp/__init__.py
myapp/myapp/myapp.py
myapp/myapp/SomeObject.py
myapp/tests/TestCase.py

Ahora estoy tratando de obtener algo como esto:

myapp.py
===================
from myapp import SomeObject
# stuff ...

TestCase.py
===================
from myapp import SomeObject
# some tests on SomeObject

Sin embargo, definitivamente estoy haciendo algo mal ya que Python no puede ver que myappes un módulo:

ImportError: No module named myapp
n0pe
fuente

Respuestas:

96

En su caso particular, parece que está intentando importar SomeObjectdesde los scripts myapp.py y TestCase.py. Desde myapp.py, haz

import SomeObject

ya que está en la misma carpeta. Para TestCase.py, haz

from ..myapp import SomeObject

Sin embargo , esto solo funcionará si está importando TestCase desde el paquete. Si desea ejecutar directamente python TestCase.py, tendría que meterse con su camino. Esto se puede hacer dentro de Python:

import sys
sys.path.append("..")
from myapp import SomeObject

aunque eso generalmente no se recomienda.

En general, si desea que otras personas usen su paquete Python, debe usar distutils para crear un script de configuración. De esa manera, cualquiera puede instalar su paquete fácilmente usando un comando como python setup.py instally estará disponible en todas partes en su máquina. Si te tomas en serio el paquete, incluso puedes agregarlo al índice de paquete de Python, PyPI .

David Robinson
fuente
Intenté simplemente usar importen mi TestCase.pypero todavía me dio el mismo error. Supongo que es porque está en un subdirectorio del __init__.py?
npe
Oh, espera, creo que lo entiendo. Si mis casos de prueba están llamando desde el paquete, ¿podré usar el from ... import ...correcto?
npe
1
Solo lo hará si TestCase se está importando desde fuera del paquete, por ejemplo, si ejecuto from myapp.tests import TestCase from a script outside myapp. If you're running python TestCase.py` dentro de la carpeta de pruebas, no puede hacer importaciones relativas
David Robinson
1
Ejecuté "pip install -e" para instalar myapp, pero cuando intento ejecutar TestCase en el código visual de estudio sigo obteniendo "ImportError: ningún módulo llamado myapp". pero si ejecuto "python" y luego en python run "desde myapp import SomeObject" funciona. ¿Qué estoy haciendo mal?
dagrun
@DavidRobinson Usé el método que ha mencionado, que no mostró ningún error después de la ejecución from fodername import file_name_of_my_py_code, pero cuando intenté acceder al objeto definido en file_name_of_my_py_code.pyél diceNameError: name 'ClassName' is not defined
Kavin Raju S
44

La función importbusca archivos en su entorno PYTHONPATH. variable y su directorio local. Por lo tanto, puede colocar todos sus archivos en el mismo directorio o exportar la ruta de acceso a un terminal ::

export PYTHONPATH="$PYTHONPATH:/path_to_myapp/myapp/myapp/"
Zenon
fuente
2
Entonces, ¿cómo puedo asegurarme de que funcione para todos los que lo usarían? Prefiero no tener que decirles que establezcan ciertas variables de entorno antes de ejecutarlo.
npe
1
el directorio actual está en pythonpath, por lo que siempre que los scripts estén en la misma carpeta / directorio, debería funcionar. desafortunadamente, cada uno de estos scripts está en directorios separados.
JKirchartz
44
Para los usuarios de Windows, en lugar de export"set PYTHONPATH =% PYTHONPATH%; C: \ path_to_myapp \ myapp \ myapp \"
loved.by.Jesus
En el código vs pude arreglar esto al agregar la variable PYTHONPATH Env a mi launch.json: "env": {"PYTHONPATH": "$ {workspaceFolder}"}
Michael Armitage
11

exportar ruta es una buena manera. Otra forma es agregar un .pth a la ubicación de los paquetes de su sitio. En mi Mac, mi python mantiene los paquetes del sitio en / Library / Python que se muestran a continuación

/Library/Python/2.7/site-packages

Creé un archivo llamado awesome.pth en /Library/Python/2.7/site-packages/awesome.pth y en el archivo coloqué la siguiente ruta que hace referencia a mis increíbles módulos

/opt/awesome/custom_python_modules
jmontross
fuente
1
en el caso estoy trabajando en las ventanas ¿cómo puedo hacer eso
Nwawel Un Iroume
No estoy seguro. En el caso de que estés usando Windows. Encuentre algún software vm y use linux. O bien, vea esta respuesta sobre la exportación de variables en Windows. stackoverflow.com/questions/559816/…
jmontross
esto es exactamente lo que necesitaba
Lee88
1
Feliz de escuchar que Lee88 @ - Me tomó un tiempo para averiguar yo mismo :)
jmontross
9

Puedes probar

from myapp.myapp import SomeObject

porque el nombre de su proyecto es el mismo que myapp.py, lo que hace que primero busque el documento del proyecto

阿 东 刘
fuente
3

En su primer directorio myapp, puede agregar un archivo setup.py y agregar dos códigos python en setup.py

from setuptools import setup
setup(name='myapp')

en su primer directorio myapp en la línea de comandos, use pip install -e. para instalar el paquete

未来 陆家嘴 顶尖 的 投资 人
fuente
2

pip installen Windows 10 por defecto se instala en 'Archivos de programa / PythonXX / Lib / site-packages', que es un directorio que requiere privilegios administrativos. Así que solucioné mi problema ejecutando pip install como Administrador (debe abrir el símbolo del sistema como administrador incluso si ha iniciado sesión con una cuenta de administrador). Además, es más seguro llamar a pip desde python.
por ejemplo, en
python -m pip install <package-name>
lugar de
pip install <package-name>

sziraqui
fuente
0

En mi caso, fue sorpresa de Windows vs Python, a pesar de que los nombres de archivo de Windows no distinguen entre mayúsculas y minúsculas, la importación de Python sí. Entonces, si tiene un Stuff.pyarchivo, debe importar este nombre tal cual.

astrowalker
fuente
0

Necesitas tener

__init__.py

en todas las carpetas que tienen código con el que necesita interactuar. También debe especificar el nombre de la carpeta superior de su proyecto en cada importación, incluso si el archivo que intentó importar está en el mismo nivel.

Krysalead
fuente