xlabel - plot python
Intento de importación relativa más allá del paquete de nivel superior (1)
Aquí está mi estructura de carpetas:
Mopy/ # no init.py !
bash/
__init__.py
bash.py # <--- Edit: yep there is such a module too
bass.py
bosh/
__init__.py # contains from .. import bass
bsa_files.py
...
test_bash/
__init__.py # code below
test_bosh/
__init__.py
test_bsa_files.py
En test_bash/__init__.py
tengo:
import sys
from os.path import dirname, abspath, join, sep
mopy = dirname(dirname(abspath(__file__)))
assert mopy.split(sep)[-1].lower() == ''mopy''
sys.path.append(mopy)
print ''Mopy folder appended to path: '', mopy
mientras que en test_bsa_files.py
:
import unittest
from unittest import TestCase
import bosh
class TestBSAHeader(TestCase):
def test_read_header(self):
bosh.bsa_files.Header.read_header()
if __name__ == ''__main__'':
unittest.main()
Ahora cuando emito:
python.exe "C:/_/JetBrains/PyCharm 2016.2.2/helpers/pycharm/utrunner.py" C:/path/to/Mopy/test_bash/test_bosh/test_bsa_files.py true
Yo obtengo:
Traceback (most recent call last):
File "C:/_/JetBrains/PyCharm 2016.2.2/helpers/pycharm/utrunner.py", line 124, in <module>
modules = [loadSource(a[0])]
File "C:/_/JetBrains/PyCharm 2016.2.2/helpers/pycharm/utrunner.py", line 43, in loadSource
module = imp.load_source(moduleName, fileName)
File "C:/Dropbox/eclipse_workspaces/python/wrye-bash/Mopy/test_bash/test_bosh/test_bsa_files.py", line 4, in <module>
import bosh
File "C:/Dropbox/eclipse_workspaces/python/wrye-bash/Mopy/bash/bosh/__init__.py", line 50, in <module>
from .. import bass
ValueError: Attempted relative import beyond toplevel package
Dado que ''Mopy "está en sys.path y bosh/__init__.py
se resuelve correctamente ¿por qué se queja sobre la importación relativa por encima del paquete de nivel superior? ¿Cuál es el paquete de nivel superior ?
Por cierto, este es mi intento de agregar pruebas a un proyecto heredado: había preguntado en el diseño del paquete de prueba de Python, pero se cerró como duplicado de ¿Adónde van las pruebas de unidad de Python? . ¡Los comentarios sobre el diseño actual de mi paquete de prueba son muy apreciados!
Bueno, la respuesta a continuación no funciona en mi caso:
El módulo bash.py es el punto de entrada a la aplicación que contiene:
if __name__ == ''__main__'':
main()
Cuando uso import bash.bosh
o from bash import bosh
obtengo:
C:/_/Python27/python.exe "C:/_/JetBrains/PyCharm 2016.2.2/helpers/pycharm/utrunner.py" C:/Dropbox/eclipse_workspaces/python/wrye-bash/Mopy/test_bash/test_bosh/test_bsa_files.py true
Testing started at 3:45 PM ...
usage: utrunner.py [-h] [-o OBLIVIONPATH] [-p PERSONALPATH] [-u USERPATH]
[-l LOCALAPPDATAPATH] [-b] [-r] [-f FILENAME] [-q] [-i]
[-I] [-g GAMENAME] [-d] [-C] [-P] [--no-uac] [--uac]
[--bashmon] [-L LANGUAGE]
utrunner.py: error: unrecognized arguments: C:/Dropbox/eclipse_workspaces/python/wrye-bash/Mopy/test_bash/test_bosh/test_bsa_files.py true
Process finished with exit code 2
Este mensaje de uso es de main () en bash.
TLDR: hacer
import bash.bosh
o
from bash import bosh
Si también tiene un constructo como bash.bash
, debe asegurarse de que su paquete tenga prioridad sobre su contenido. En lugar de agregar, agréguelo al frente del orden de búsqueda:
# test_bash/__init__.py
sys.path.insert(0, mopy)
Cuando tu lo hagas
import bosh
Se importará el módulo bosh
. Esto significa que Mopy/bash
está en tu sys.path
, python encuentra el archivo bosh
allí, y lo importa. El módulo ahora es conocido globalmente por el nombre bosh
. Si bosh
es en sí mismo un módulo o paquete no importa para esto, solo cambia si se bosh.py
o bosh/__init__.py
.
Ahora, cuando bosh
trata de hacer
from .. import bass
esto no es una operación del sistema de archivos ("one directory up, file bass") sino una operación de nombre de módulo. Significa "un paquete de nivel, módulo bajo". bosh
embargo, bosh
no se importó de su paquete, pero sí solo. Por lo tanto, no es posible subir un paquete: terminas en el paquete ''''
, que no es válido.
Echemos un vistazo a lo que sucede cuando lo haces
import bash.bosh
en lugar. Primero, se importa el paquete bash
. Luego, bosh
se importa como un módulo de ese paquete : se conoce globalmente como bash.bosh
, incluso si usó from bash import bosh
.
Cuando bosh
hace
from .. import bass
ese funciona ahora: subir un nivel desde bash.bosh
te lleva a bash
. A partir de ahí, el bass
se importa como bash.bass
.
Consulte también esta respuesta relacionada para ejecutar un módulo desde un paquete sin modificar sys.path
.