Импорт Python из байтового ввода-вывода (или, в более общем случае, из объекта в памяти)

Контекст:

В настоящее время у меня есть программа, которая загружает набор плагинов из их путей к файлам (на подключенном сетевом диске), используя метод, показанный в другом потоке SO. . Эти плагины предназначены для непрерывного выпуска, а это значит, что мне нужен постоянный доступ для их написания. Текущий механизм блокирует файлы, поэтому я должен попросить всех закрыть программу, чтобы я мог обновить файлы.

Вопрос:

Мне было интересно, есть ли способ, возможно, используя метод, аналогичный указанному выше, импортировать файл из объекта io.BytesIO необработанного содержимого плагина (следовательно, разблокировать файл, чтобы я мог вносить изменения по своему усмотрению).

В более общем плане:

В частности, могу ли я хранить необработанное содержимое модуля в памяти, не касаясь физического диска? Если это невозможно, есть ли способ полностью загрузить эти модули в память, чтобы затем разблокировать импортируемые файлы?

Как я уже говорил в своем комментарии, я понимаю, что вы можете смонтировать виртуальную файловую систему в ОС на базе Linux (что могло бы решить мою проблему), хотя, к сожалению, я разрабатываю для Windows, и Microsoft никогда не сможет облегчить вашу жизнь! :-)

Примечание.

Я не спрашиваю, где я могу скопировать эти файлы, чтобы импортировать их из локальной версии (например, temp, cache и т. д.).

Я понимаю, что это довольно специализированный вопрос, поэтому любая помощь очень ценится.


person Minion Jim    schedule 12.04.2020    source источник
comment
Интересно. В основном из любопытства, если вы загружаете плагин (модуль?) в байтах, не означает ли это, что вам также придется обновлять код модуля в байтах? (Я уверен, что я что-то упускаю здесь...).   -  person S3DEV    schedule 13.04.2020
comment
@ S3DEV, я бы читал модули с сетевого диска в BytesIO, поэтому, хотя я не уменьшаю нагрузку на чтение и запись на диске, я просто оставляю файлы открытыми в течение минимального времени (с количеством пользователей , у меня статистически никогда не будет проблем)   -  person Minion Jim    schedule 13.04.2020
comment
Я правильно понимаю, что вы не хотите делать локальные копии файлов удаленного модуля Python? Вероятно, существует компромисс, который достигается за счет сохранения в памяти копии файлов. Возможно, с комбинацией tempfile.SpooledTemporaryFile и io.StringIO. Или, может быть, со сторонней библиотекой, например, я случайно наткнулся на memory-tempfile.   -  person sinoroc    schedule 13.04.2020
comment
@sinoroc, вы правы, я пытаюсь избежать копирования модулей на локальный диск, и идеальным вариантом был бы импорт из версии в памяти (или принуждение Python к выпуску исходного файла после импорта). У меня нет проблем с получением модулей в любом из перечисленных форматов, но для импорта из них я не могу найти метод (в случае tempfile.SpooledTemporaryFile мне пришлось бы записать его на диск, прежде чем его можно будет импортировать)   -  person Minion Jim    schedule 13.04.2020
comment
Если бы я мог получить путь к файлу, указывающий на объект в памяти без необходимости записи, это также отлично решило бы проблему. Я знаю, что в ОС на основе Linux вы можете монтировать файловую систему прямо из ОЗУ, но я сомневаюсь, что Microsoft может быть настолько полезна :-)   -  person Minion Jim    schedule 13.04.2020
comment
Понимаю. Думаю, в вашей ситуации я бы попытался проследить пути кода и определить, какая часть (если есть) importlib (или более низких уровней) действительно нуждается в файле в файловой системе. Или определите, почему файлы не освобождаются после импорта в кэш модуля Python. Или, может быть, переосмыслить все это и принять, что запись чего-то в локальной файловой системе может быть приемлемым компромиссом.   -  person sinoroc    schedule 13.04.2020


Ответы (1)


Хотя я не был из объекта io.BytesIO, как я изначально просил, я смог импортировать модуль из его источника после того, как нашел это невероятно полезная статья. Я не копировал сюда код, так как он довольно большой, хотя мне удалось заставить его успешно импортировать виртуальный модуль.

Следующий код после того, как я изменил загрузчик, чтобы удалить общий префикс, и создал класс модуля, сначала выполнив исходный код, получив из него globals и, наконец, используя метод Python type для создания класса модуля.

Это не особенно красиво и определенно нарушает некоторые рекомендации по стилю Python, поэтому я определенно открыт для улучшений!

source = """def hello():
    print("I don't want to say hi to the world")"""
name = "my_module"

glo = {}
exec(source, glo)

injector = DependencyInjector()
injector.provide(name, type(name, (), glo))
injector.install()

foo = __import__(name)
foo.hello()
person Minion Jim    schedule 13.04.2020