Как правильно запустить проект python из другого каталога - PullRequest
0 голосов
/ 07 мая 2020

python иерархия файлов проекта:

parent/
    __init__.py
    one/
        __init__.py
        bar.py
    two/
       __init__.py
       foo.py

foo.py

from one import bar

Я попытался запустить foo.py с терминала в другом каталоге (например, пользователи / пользователь), я получил следующую ошибку:

Нет модуля с именем one

Когда я пытаюсь запустить foo.py, я думаю, он пытается импортировать файлы из каталога, из которого был выполнен код, я перепробовал много способов и не смог найти решения наконец-то я нашел решение, проблема с этим решением в том, что оно не изящно, и я надеюсь, что есть элегантное и лучшее решение.

foo.py

from pathlib import Path
import sys

sys.path.append(str(Path(__file__).parent.parent))
sys.path.append("..")

from one import bar
  • Это решение не изящно, поскольку не позволяет мне помещать весь импорт в начало страницы.

Ответы [ 2 ]

0 голосов
/ 08 мая 2020

Почему вы не позволяете родителю действовать как поставщик пути для ребенка, создавая словарь путей? вот так:

class parent:
...
    def createPathDict(self):
        self.path_dict = {}
        self.path_dict ['parent'] = self.parentPath
        self.path_dict ['one'] = os.path.join(self.parentPath, 'one')
        self.path_dict ['two'] = os.path.join(self.parentPath, 'two')
        # self.path_dict ['three'] = …
        # ...

Из дочернего 'two' вы импортируете словарь следующим образом (я предполагаю, что вы используете классы):

class foo:

    def __init__(self, parent):
          self.parent = parent

    def addPathsToPythDirs(self):
         sys.path.insert(1, self.parent.path_dict ['one'])  # better
         # sys.path.insert(0, self.parent.path_dict [key])  
...

Таким образом вы можете сохранить свой импорт в foo.py

Зачем использовать sys.path.append (путь) вместо sys.path.insert (1, путь)?

0 голосов
/ 07 мая 2020

Тот факт, что у вас есть __init.py__ в каталоге parent, предполагает, что parent является частью структуры вашего пакета и что его родительский каталог , каким бы он ни был, должен находиться в ПУТИ. Следовательно, ваш импорт действительно должен быть:

from parent.one import bar

Для структуры каталогов приложения может быть полезно иметь один root. Затем __init.py__ в этом единственном пакете root можно использовать для загрузки модулей из подпакетов, но это, конечно, не является обязательным требованием. Если это не было вашим намерением, вам, вероятно, следует удалить __init__.py, который находится в parent, поскольку он не служит цели (и сбивает с толку), и убедитесь, что каталог parent находится в вашем PATH.

ОДНАКО : до тех пор, пока текущий каталог, в котором вы находитесь, когда вы запускаете свою программу, является родительским каталогом для root (ов) вашей структуры пакета, Python должен иметь возможность найти ваши пакеты без каких-либо специальных действий с вашей стороны, потому что текущий каталог автоматически добавляется к пути. Если это неудобно, вы можете установить переменную среды PYTHONPATH .

Итак, определите, следует ли вам изменять оператор импорта или нет, в зависимости от того, какие каталоги являются частью структуры вашего пакета. Затем вы должны настроить Python, чтобы найти ваши пакеты, установив текущий каталог, PYTHONPATH или sys.path в требуемый каталог, но сделайте это один раз. Если вам нужно установить sys.path, я бы сделал это в вашей основной программе при запуске, прежде чем она должна будет что-либо включать:

Если foo.py - ваша основная программа, то в в верхней части программы у меня было бы:

if __name__ == '__main__':
    from pathlib import Path
    import sys

    # if your import statement is: from parent.one import bar, then:
    sys.path.insert(0, str(Path(__file__).parent.parent))
    """
    # if your import statement is: from one import bar, then:
    sys.path.insert(0, str(Path(__file__).parent))
    """
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...