Импортируйте скрипт из родительского подкаталога, имя файла и каталога которого начинаются с цифр

Я знаю обычную систему импорта Python, пакеты, __init__.py, функцию __import__ (см. В Python, как импортировать имя файла начинается с цифры ) и т. д. Я знаю классическую Как мне импортировать другие файлы Python?ответы.

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

|
|- 1 UTILS
|     |-  123myscript.py
|- 2 TESTS
|     |-  test.py

Как при запуске test.py импортировать 123myscript.py, не искажая sys.path.append?

Возможно ли это с importlib? Мне не удалось это сделать с помощью:

importlib.import_module("../1 UTILS/123myscript.py", package=None)

Взгляните на это: github.com/tortoise/aerich/blob/…

Waket Zheng 03.06.2024 11:13

проверьте здесь stackoverflow.com/questions/67631/…

Andrio Skur 18.06.2024 16:12

Функция importlib.import_module работает только с именами модулей в пространстве имен модулей Python. Он не принимает пути к файлам, поскольку для поиска модулей использует пути поиска модулей Python (например, sys.path). Чтобы импортировать модуль из определенного пути к файлу, вы должны использовать функции importlib.util, как показано в ответе @simon.

safiqul islam 24.06.2024 11:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
160
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я попробовал несколько подходов, но этот работает: сначала мы создаем символическую ссылку «1 UTILS/123myscript.py» -> «2 TESTS/myscript.py», затем импортируем через библиотеку importlib. Вот содержимое файла «2 TESTS/test.py»:

# File: 2 TESTS/test.py

import importlib
import pathlib

# Create symlink "1 UTILS/123myscript.py" -> "2 TESTS/myscript.py"
utils_dir = pathlib.Path(__file__).parent.with_name("1 UTILS")
myscript_path = utils_dir / "123myscript.py"
temp = pathlib.Path(__file__).with_name("myscript.py")
temp.symlink_to(myscript_path)

# Import and clean up
myscript = importlib.import_module("myscript")
temp.unlink()
# Now we can work with the `myscript` module

Другие подходы, которые я пробовал и потерпел неудачу

  • cd в «1 UTILS» перед импортом
  • Добавьте абсолютный путь для «1 UTILS» в sys.path перед импортом.
Ответ принят как подходящий

Прагматичный ответ дан в соответствующем вопросе, на который комментарий Андрио Скура дает ссылку. Действительно, он использует importlib.

В соответствии с вашим случаем это может выглядеть следующим образом. Вот, я предполагаю

  • Используется Python 3.5+ (пробовал с 3.11.9);
  • структура папок точно такая же, как указано в вашем вопросе;
  • файл 123myscript.py содержит следующий код:
    # Contents of `1 UTILS/123myscript.py`
    def do_something():
        return 42
    

Тогда успешный импорт 123myscript.py в test.py будет, например:

# Contents of `2 TESTS/test.py`
import importlib.util
from pathlib import Path

location = Path(__file__).parents[1] / "1 UTILS" / "123myscript.py"

spec = importlib.util.spec_from_file_location(location.stem, location)
# ^ Instead of `location.stem` (thus "123myscript"), you can use an arbitrary name
myscript = importlib.util.module_from_spec(spec)
spec.loader.exec_module(myscript)
assert myscript.do_something() == 42

Обратите внимание: я не знаю, есть ли какие-либо зависимости в 123myscript.py, что может усложнить настройку.

Другие вопросы по теме