Крюк импорта Python для добавления пути

#python #python-import

Вопрос:

Я пытаюсь исправить свой импорт «библиотеки», учитывая структуру каталогов QuantConnect. То, как они организуют «пользовательские библиотеки», является таковым:

Допустим, я создаю проект под названием «Проект», который с помощью выбора пользовательского интерфейса выбрал библиотеку под названием «Утилиты». QC создает следующую структуру папок:

 .
├── Project
    |── main.py
├── Library
    ├── Utilities
        ├── Whatever.py
 

Однако возникает проблема с тем, как QC импортирует библиотеку «Утилиты». Это достигается путем импорта всего содержимого каталога при удалении имени каталога верхнего уровня. Вы можете думать о результирующей структуре как таковой:

 .
├── Project
    |── main.py
    ├── Whatever.py
 

В результате я больше не могу пользоваться from Utilities.Whatever import * . Поэтому, чтобы смягчить эту проблему на их платформе, я поместил все содержимое каждой библиотеки в папку с тем же именем. Таким образом, исходная структура теперь выглядит следующим образом:

 .
├── Project
    |── main.py
├── Library
    ├── Utilities
        ├── Utilities
            ├── Whatever.py
 

…и конечная структура выглядит так:

 .
├── Project
    |── main.py
    ├── Utilities
        ├── Whatever.py
 

Теперь импорт работает так, как и ожидалось. Только теперь они работают, как и ожидалось, только через онлайн — «лабораторию алгоритмов» QC, но не локально! Я не могу изменить этот макет, так как КК импорта своих пользователей библиотеки, поэтому мне нужно создать скрипт Python импорт крюк, который попытается найти переменную среды, что, если он не задан, по умолчанию не выполняет крючка; но, когда нашли, это, как предполагается, работает в режиме нон-КК среду и подставляла 1-го уровня справочника импортное название. т. е., переводя from Utilities.Whatever import * на from Utilities.Utilities.Whatever import * .

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

Комментарии:

1. Простой. Просто добавьте try-catch блок в импорт. Попробуйте синтаксис импорта QC , поймайте ImportError, а затем попробуйте свой собственный синтаксис локального импорта.

2. Опять же, я понятия не имею, что такое QuantConnect, но я буквально просто катаюсь с ним

3. В этом первом случае я не уверен, что вы подразумеваете под «импортом всего содержимого каталога». Это Library/Utilities внутри sys.path ? На самом деле, в чем sys.path дело ?! он должен содержать все каталоги, которые сканирует python. Я думаю, вы могли бы написать setup.py на том же уровне, что и main.py который ищет пакеты в библиотеке/утилит. Затем выполните «установку разработчика» с помощью pip. Тогда вы могли бы просто использовать ту же структуру, что и веб-сайт.

4. QuantConnect-это торговая платформа, которая позволяет людям использовать C#/Python для программирования алгоритмов. Что я подразумеваю под импортом всего содержимого, так это то, что когда я (через пользовательский интерфейс лаборатории алгоритмов) выбираю библиотеку утилит в качестве ссылки на библиотеку для проекта, все содержимое Утилит отображается в корневом каталоге проекта, но не в самом каталоге утилит. Я сделал несколько иллюстраций каталога, в которых говорится об этом.

5. @rv.kvetch существует слишком много файлов, которые ссылаются на импорт этих утилит, чтобы сделать это эффективно.

Ответ №1:

В итоге я создал два файла с именем ‘Library.py». Один был пуст и помещен внутрь Library/Utilities/Utilities , а другой (не пустой) был помещен внутрь Library/Utilities . Так что теперь, когда я набираю import Utilities.Library любой заданный сценарий, запускаемый в среде контроля качества, ничего не происходит (как и должно быть), потому что Library.py файл, на который ссылается ссылка, пуст; когда он запускается в локальной среде, выполняется следующий код:

 import os
import sys

# Use env variable to ensure we only update the sys path once
env_check = 'Checked-Library-Environment'
if os.environ.get(env_check) is None:
    os.environ[env_check] = 'True'

    _path = None
    path = os.getcwd()
    target = "Library"
    library = None

    # Stop searching when we've reached the root
    while path is not _path:
        test_path = os.path.join(path, target)
        if os.path.isdir(test_path):
            library = test_path
            break
        _path = path
        path = os.path.dirname(path)

    # If we've found the Library directory, add its contents to the module path list
    if library is not None:
        for name in os.listdir(library):
            path = os.path.join(library, name)
            if not path in sys.path:
                sys.path.append(path)