Python: Как выбрать один из нескольких сценариев в качестве пакета для импорта в основной сценарий, если он находится в разных каталогах? - PullRequest
1 голос
/ 27 марта 2020

У меня есть несколько проектов, которым нужен общий сценарий (main.py), но мне нужно, чтобы у них были разные функции, определенные c для каждого проекта. Это означает, что когда я запускаю сценарий для использования в проекте A, я хочу иметь возможность импортировать его configA.py, но импортировать configB.py при запуске его для проекта B.

Например, сказать, что и в configA.py, и в configB.py существует разное определение одной и той же функции foo(). Моя цель - иметь возможность выполнить что-то вроде python3 main.py ../../ProjectA/Config/configA.py для проекта A и аналогично для B. Затем внутри main.py скрипт импортирует переданный ему файл (что-то вроде config = import_module(sys.argv[0])), а затем быть в состоянии запустить config.foo(), который будет вести себя по-разному в зависимости от того, какой файл был передан.

Из прочтения нескольких постов помощи на SO, я видел, что многие люди предлагают importlib.import_module(), так как я могу передать имя пакета в качестве аргумента main.py. Но небольшое осложнение по сравнению с другими постами, которые я прочитал, связано с моей файловой структурой. Кажется, что import_module() действительно работает только тогда, когда файлы main / package находятся в том же каталоге, или когда основной скрипт находится в родительском каталоге пакета. Однако моя файловая структура выглядит следующим образом:

└─ Documents
   ├─ Common
   │  └─ Scripts
   │     └─ main.py
   ├─ ProjectA
   │  └─ Config
   │     └─ configA.py
   └─ ProjectB
      └─ Config
         └─ configB.py

Можно ли импортировать выбранный мной пакет для использования в main.py с учетом этой файловой структуры?

1 Ответ

1 голос
/ 27 марта 2020

Вы можете использовать оператор if для различных импортов:

import os
import sys

sys.path.insert(0, os.abspath('../..'))  # this is important so the packages are on the path

if sys.argv[1] == 'A':
    from ProjectA.Config.configA import foo
elif sys.argv[1] == 'B':
    from ProjectB.Config.configB import foo
else:
    raise ImportError(f'No module corresponding to {sys.argv[1]}')

Или вы также можете использовать importlib.import_module вместо if/else цепочки:

import importlib

module = importlib.import_module('Project{x}.Config.config{x}'.format(x=sys.argv[1]))
foo = module.foo

И затем используйте через

python main.py A  # use foo from configA
python main.py B  # use foo from ConfigB

Выполните через -m из Documents

Альтернативой модификации sys.path является запуск main.py через переключатель -m изнутри Documents каталог. При запуске python main.py каталог скрипта будет помещен в путь. При запуске python -m Common.Scripts.main текущий рабочий каталог будет помещен в путь и, следовательно, ProjectA и ProjectB автоматически обнаруживаются:

$ pwd
/path/to/Documents
$ python -m Common.Scripts.main
...