Python сбой импорта модулей - PullRequest
0 голосов
/ 07 января 2020

Я проверил похожие вопросы, но ничего не ответил на мой вопрос. Как и в другом посте, моя структура пакета выглядит следующим образом:

mypackage/  
    __init__.py
    mymodule.py
    utils/ 
        __init__.py
        common.py
        myutils1.py
    data_classes/ 
        __init__.py
        command_file.py
        myclass.py

Мне нужно использовать этот пакет несколькими способами: 1) импортировать пакет и использовать его в больших сценариях 2) запустить некоторые модули как отдельные (например: python3 myutils1.py)

myutils использует функции от общих, для этого я попытался

A)

from PySfmc.utils import common #directly in myutils.py 

B)

from mypackage import utils         # in __init__.py
from mypackage.utils import common # in myutils.py 

C)

 import common #directly in myutils.py 

et c

Короче говоря ... Мне не удалось получить что-то, что успешно импортирует оба при импорте в пакет в реплее И при запуске python3 myutils.py

у кого-нибудь есть идеи, что я делаю не так?

Спасибо !!


редактировать, я угадайте, что сводится к тому, что: из repl я могу сделать одно из следующих действий:

from mypackage.folder.file import function
from mypackage.folder import file
from mypackage import folder

, но если я напишу то же самое внутри myutils1.py, то это не получится


edit2 :

Я отредактировал setup.py из следующей строки:

packages=['mypackage'],

до

packages=['mypackage','mypackage.data_classes','mypackage.utils']

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

есть ли веская причина, почему я не должен этого делать? он кажется менее хакерским, чем другие предлагаемые решения.

Ответы [ 3 ]

0 голосов
/ 07 января 2020

Если вы хотите запустить его как пакет и как отдельный модуль, вы можете добавить это к myutils.py, это хакерски, но это будет работать:

import os
import sys
_package_path = os.path.dirname(
    os.path.dirname(
        os.path.abspath(__file__)
    )
)
sys.path.insert(0, _package_path)

В myutils1.py вы можете импортировать a_function из common.py вот так:

from utils.common import a_function

В mymodule.py вы можете импортировать b_function из myutils1.py так:

from utils.myutils1 import b_function
0 голосов
/ 07 января 2020

Обычно сценарии находятся не в самом пакете, а в отдельном каталоге (чаще всего называемом «bin») на том же уровне, что и сам каталог пакета проекта, ie:

myproject/
    bin/
        myutils1.py
        otherscript.py
    mypackage/  
        __init__.py
        mymodule.py
        utils/ 
            __init__.py
            common.py
        data_classes/ 
            __init__.py
            command_file.py
            myclass.py

Таким образом, скрипт использует только абсолютный импорт (from mypackage.somemodule import whatever) и полагается на то, что mypackage доступен в sys.path - что делается с помощью , что делает ваш пакет корректно устанавливаемым , а позволяет вам установить скрипты где-нибудь в вашем PATH .

Это, конечно, правильно работает только при правильной установке - если вы попытаетесь запустить python bin/myutils1.py из myproject, пакет все равно не будет найден. Это можно решить, вставив правильный путь (путь к myproject в начале sys.path:

#  bin/myutils1.py
import sys
import os
__PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if __PROJECT_DIR not in sys.path:
    sys.path.insert(0, __PROJECT_DIR)

from mypackage.utils import common

Но вы можете сделать это только в том случае, если вы не планируете делать правильно Устанавливаемый пакет (если ваш пакет установлен должным образом, возмущение sys.path не только бесполезно, но даже, возможно, вредно), а затем еще проще просто переместить ваши сценарии прямо в верхнюю часть каталога проекта (просто выше *). 1022 * dir вашего пакета), поэтому python во время выполнения уже установит sys.path правильно:

myproject/
    myutils1.py
    otherscript.py
    mypackage/  
        __init__.py
        mymodule.py
        utils/ 
            __init__.py
            common.py
        data_classes/ 
            __init__.py
            command_file.py
            myclass.py
0 голосов
/ 07 января 2020

Если вы хотите запустить свой пакет автономно, вам нужно создать стартер вне пакета.

starter.py
mypackage/  
    __init__.py
    mymodule.py
    utils/ 
        __init__.py
        common.py
        myutils1.py
    data_classes/ 
        __init__.py
        command_file.py
        myclass.py

starter.py должен иметь этот код:

import mypackage.utils.myutils.py

Если вы запустите starter.py, он будет работать.

Вы можете найти реальный пример в одной из моих программ . Эта программа может быть запущена напрямую с помощью jdTextEdit.py, который просто импортирует пакет jdTextEdit и может быть установлен как модуль вместе с setup.py. Надеюсь, это то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...