Как я могу автоматически настроить глобальный для каждого импортируемого файла в Python?

#python #module #import

#python #модуль #импорт

Вопрос:

У меня большой код на python со множеством модулей и классов. У меня есть специальный класс, единственный экземпляр которого необходим повсюду в коде (это многопоточное приложение, и этот экземпляр класса также содержит локальное хранилище потоков, блокировки и т. Д.). Немного неудобно всегда «заполнять» этот экземпляр в каждом импортированном модуле. Я знаю, что использование глобальных файлов — не лучшая практика, но в любом случае: есть ли в python какой-либо «импортный хук», чтобы я мог подключиться к нему, чтобы мой экземпляр был доступен во всех модулях без дополнительной работы? Он должен работать для обычного импорта, «из mod import …» тоже, и для конструкций импорта тоже. Если это невозможно, можете ли вы предложить лучшее решение? Конечно, неинтересно передавать этот экземпляр конструкторам всех классов и т. Д… Наследование также не помогает, поскольку у меня есть модули без классов, а также мне нужен один экземпляр, а не сам класс…

 class master():
    def import_module(self, name):
        mod = __import__(name)
        mod.m = self
        return mod
[...]
m = master()
  

В настоящее время я думаю примерно так: но тогда я должен использовать m.import_module() для импорта модулей, тогда у других модулей будет экземпляр мастер-класса с именем «m», поэтому я тоже могу использовать m.import_module() и т.д. Но тогда я должен отказаться от использования «обычных» операторов импорта, и я должен написать это:

 example_mod = m.module_import("example_mod")
  

вместо этого:

 import example_mod
  

(но наверняка я тоже могу это сделать, чтобы присвоить «m» example_mod.m тогда)

Ответ №1:

Конечно, неинтересно передавать этот экземпляр конструкторам всех классов

Вам не обязательно это делать. Настройте свой глобальный класс в подобном модуле config и импортируйте его

 # /myapp/enviroment/__init__.py

class ThatSingleInstanceClass: pass

# create the singleton object directly or have a function init the module
singleton = ThatSingleInstanceClass() 



# /myapp/somewhere.py

# all you need to use the object is importing it
from myapp.enviroment import singleton

class SomeClass:

    def __init__(self): # no need to pass that object
        print "Always the same object:", singleton
  

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

1. Большое спасибо! Кажется, мне еще многому нужно научиться, до этого я бы предположил, что импорт instace приводит к разным экземплярам, но теперь я хорошо понимаю, что если модуль импортирован, это пространство имен используется, даже если оно импортировано из другого модуля, поэтому оно не будет новым. Просто мне любопытно, достаточно ли это грязно, если у меня есть имя класса master, тогда я создаю экземпляр с именем master [итак, то же имя] 🙂 Итак, после этого никакие другие модули не могут импортировать сам класс по ошибке, только экземпляр 🙂 Это работает для меня в любом случае.

2. @LGB: если вы следуете pep8 (вы должны), вы бы назвали свой класс Master (классы используют PascalCase в python), и тогда не возникнет конфликта с master экземпляром — за исключением того, что вы должны выбрать более значимое имя переменной? Как люди используют переменную? Назовите это так.

Ответ №2:

Что плохого в том, что каждый модуль импортирует необходимый объект? Явное лучше, чем неявное.

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

1. Ну, это тоже некрасиво, поскольку этот экземпляр часто используется, поэтому я хочу поместить его в глобальное пространство имен импортируемого мода, поэтому мне не нужно каждый раз писать «self»: если я передам экземпляр моего «master» класса конструкторукласс в импортированном модуле, для этого нужен уродливый хак, чтобы сказать «global m», а затем «m = m_in», где m_in — параметр для конструктора. Другое решение — поместить в пространство имен класса, но тогда я должен использовать его в других методах как «self.something». Поскольку в python есть некоторые глобальные переменные, такие как sorted() , я бы хотел, чтобы мой «m» везде был глобальным.

2. Смотрите ответ @Йохена Ритцеля. Это то, что я имел в виду.

3. Хорошо, извините, я совершенно неправильно понял. Я согласен, просто — кажется — у меня были проблемы с пониманием деталей импорта python 🙂