0

Независимо от того, как я структурировать импорт в файлах код и в __init__.py файлах, я не могу показаться, чтобы получить это право для выполнения программы и выполнения тестов с использованием pytest. Как мне нужно написать импорт, когда моя структура проекта выглядит следующим образом:импорт Python с __init__.py

src/ 
    __init__.py 
    VocableFileWriter.py 
    WordListHelper.py 
    WordListReader.py 
    XLDAttributeValueAdder.py 

    exceptions/ 
     __init__.py 
     XMLInvalidException.py 
     XMLParseException.py 

    gui/ 
     __init__.py 
     GTKSignal.py 
     XLDAttributeValueAdderWindow.py 

    test/ 
     __init__.py 
     test_XLDAttributeValueAdder.py 

    xmlparser/ 
     __init__.py 
     XMLParser.py 

В настоящее время я их так:

В __init__.py файлов у меня есть импорт, как это (src/__init__.py):

from src import * 
from src.exceptions import * 
from src.xmlparser import * 

и в подпакет (src/xmlparser/__init__.py):

from src.xmlparser import * 

Итак, я думаю, что это абсолютные по проекту пути к модулям. В коде сами файлы импортировать как это:

import os 
import sys 
from VocableFileWriter import VocableFileWriter 
from XLDAttributeValueAdder import XLDAttributeValueAdder 

Однако, когда я выполнить код из каталога выше src с помощью:

./src/main.py 

Он мне говорит, что:

Traceback (most recent call last): 
File "./src/main.py", line 6, in <module> 
    from VocableFileWriter import VocableFileWriter 
File "/home/xiaolong/Development/PycharmProjects/xld-attribute-value-adder/src/VocableFileWriter.py", line 2, in <module> 
    from XMLInvalidException import XMLInvalidException 
ImportError: No module named 'XMLInvalidException' 

Раньше это был проект PyCharm, но я не мог заставить его работать с структурой импорта PyCharm, используемой, когда вы не используете PyCharm, но запускаете ее с терминала. Я решил, что хочу взять все импортные вещи в свои руки. Поэтому не смущайтесь тем, что он находится в директории PyCharm.

Я также хочу, чтобы иметь возможность выполнять тесты с использованием, например:

py.test src/test/test_XLDAttributeValueAdder.py 

Как решить эту кашу?

Edit # 1: У меня была программа работает один раз, а затем тест жаловался о недостающих модулей, вероятно, потому, что в другом подкаталоге, и я попытался так много конфигураций, что я не знаю, как у меня было программа работает больше. Если возможно, добавьте некоторое объяснение, почему определенная структура правильная и работает как для тестов, так и для самой программы.

EDIT # 2: Мне удалось запустить тесты, но теперь программа больше не запускается. Я опустошил все __init__.py файлы и используются только пути для проекта абсолют в коде файлов, как это (src/test/test_XLDAttributeValueAdder.py):

from src.VocableFileWriter import VocableFileWriter 
from src.WordListHelper import WordListHelper 
from src.WordListReader import WordListReader 
from src.XLDAttributeValueAdder import XLDAttributeValueAdder 
from src.exceptions.XMLInvalidException import XMLInvalidException 
from src.exceptions.XMLParseException import XMLParserException 
from src.xmlparser.XMLParser import XMLParser 
from src.test.path_helper import go_up 
from src.test.path_helper import go_in 

и в main.py:

from src.VocableFileWriter import VocableFileWriter 
from src.XLDAttributeValueAdder import XLDAttributeValueAdder 

выходе ./src/main.py:

./src/main.py 
Traceback (most recent call last): 
File "./src/main.py", line 6, in <module> 
    from src.VocableFileWriter import VocableFileWriter 
ImportError: No module named 'src' 

РЕДАКТИРОВАТЬ # 3: Я пробовал относительный импорт способ, как это:

  • main.py переехал один каталог вверх

Структура теперь выглядит следующим образом:

main.py 

src/ 
    __init__.py 
    VocableFileWriter.py 
    WordListHelper.py 
    WordListReader.py 
    XLDAttributeValueAdder.py 

    exceptions/ 
     __init__.py 
     XMLInvalidException.py 
     XMLParseException.py 

    gui/ 
     __init__.py 
     GTKSignal.py 
     XLDAttributeValueAdderWindow.py 

    test/ 
     __init__.py 
     test_XLDAttributeValueAdder.py 

    xmlparser/ 
     __init__.py 
     XMLParser.py 
  • __init__.py файлы пустые
  • main.py файл получает относительный

Imports выглядеть следующим образом:

import os 
import sys 
from .src.VocableFileWriter import VocableFileWriter 
from .src.XLDAttributeValueAdder import XLDAttributeValueAdder 

Когда я пытаюсь запустить main.py файл:

Traceback (most recent call last): 
File "main.py", line 6, in <module> 
    from .src.VocableFileWriter import VocableFileWriter 
SystemError: Parent module '' not loaded, cannot perform relative import 

Однако есть __init__.py файл в том же каталоге, что и файл main.py, также пустой.

+0

The * main.py * файл не должен использовать относительный импорт, когда вы намерены назвать его непосредственно. Вы переместили его за пределы структуры пакета, так что это независимый модуль и подходит для использования абсолютного импорта для пакета. Я уточню свой ответ. – tynn

ответ

1

Лучше использовать относительный импорт.

При выполнении from src import * в src/__ init__.py вы импортируете все, что вы определили, прежде чем вызывать импорт. Скорее всего, это просто ничего. Если вы определили переменную __all__, вы получите из нее подмодуль, но, возможно, также AttributeError, если переменная еще не определена.

Так вместо того, чтобы импортировать модули, нужно явно где вы нуждаетесь в них, как

from .VocableFileWriter import VocableFileWriter 
from .exceptions.XMLInvalidException import XMLInvalidException 

или позволяет сказать, что в ЦСИ/GUI/GTKSignal.py

from ..exceptions.XMLInvalidException import XMLInvalidException 

Также вы можете использовать project- абсолютные пути, как указано в вашем Редактировать # 2.


Кроме того, у вас есть проблема с вашим путем при вызове ./src/main.py. В этом случае каталог, содержащий src, не находится в пути. Вместо этого ./src/ находится на пути. Поэтому python больше не считает его пакетом, и поскольку нет другого пакета с этим именем, импорт невозможен.

Вместо этого разместите свой модуль main.py в том же каталоге, что и в пакете src, или называйте его модулем с python -m src.main. Сделав это, вы также можете переименовать его в src/main .py и позвонить в пакет instad с помощью python -m src.


При использовании первого подхода, main следует использовать абсолютную структуру импорта. Подумайте об этом как о модуле, который вы кладете где-нибудь на свой компьютер, в то время как ваш пакет src находится где-то в другом месте, где он может быть найден Python, как и любой другой модуль или пакет, установленные системой. Это не так, потому что он расположен помимо самого пакета, поскольку текущий каталог находится в sys.path.

main.py

import os 
import sys 
from src.VocableFileWriter import VocableFileWriter 
from src.XLDAttributeValueAdder import XLDAttributeValueAdder 
+0

Проект абсолютной вещи не всегда работает. Например, для тестов это не работает. Я думаю, это потому, что они находятся в другом каталоге, или каталог, из которого выполняется pytest, отличается от верхнего уровня моего проекта, который я использую при выполнении программы. Я проверю относительный импорт. – Zelphir

+0

Я пытался использовать относительный импорт, когда main.py не находится за пределами папки src, но также приводит к ошибке. Помещение файла main.py за пределы файла src кажется странным, поскольку оно является частью моей программы и на самом деле является файлом исходного кода. Если возможно, я хочу, чтобы он оставался в папке src. Вот ошибка, которую я получаю, используя относительный импорт, файл main.py находится внутри каталога src: «Traceback (последний последний вызов): Файл« ./src/main.py », строка 6, в из .VocableFileWriter import VocableFileWriter SystemError: родительский модуль «не загружен, не может выполнять относительный импорт» – Zelphir

+0

@Zelphir. Затем вы должны называть его «python -m src.main». Если вы вызываете его с помощью './Src/main.py', он рассматривается как автономный модуль, а не подмодуль вашего пакета src. – tynn

Смежные вопросы