Экспорт модуля python (в файл string или py)

Резюме: Я хочу взять переменную типа 'module' и экспортировать ее.

Я импортирую модуль python из .py-файла с помощью импорта и внося изменения в него. Мне нужно экспортировать модуль обратно в файл или получить строковое представление полного модуля, который затем можно записать на диск.

Мне не удалось найти какой-либо способ экспортировать модуль python или способ преобразования объектов в модуле в строки в структурированном, обычном текстовом исполняемом формате python. (не json, травление и т. д.)

Подробный вопрос и использование: это требование является частью внутреннего процесса сборки; нет требований к безопасности, и только наши собственные модули, а не встроенные модули, изменяются. Сценарий python работает с бизнес-логикой для изменения ряда других скриптов. Этот процесс использует информацию, доступную только во время сборки. В результате у меня нет возможности импортировать модуль с различными данными во время выполнения.

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

Что я сделал С помощью сценария мастер-генератора, написанного на python, я могу импортировать несколько модулей (которые имеют только объявления переменных и не имеет исполняемого кода) и сделать все необходимые замены. Я остался с переменной типа модулем, который мне нужно экспортировать обратно в файл, чтобы впоследствии был выполнен.

У @abarnert были хорошие идеи. Я не знал о функции репрезентации. Это дало мне информацию, но без форматирования. Это заставило меня взглянуть на pprint, который был настолько близок, насколько я догадывался, что бы я предпочел.

Пример example.py

sample = { 'level1_dict_1' : { 'key1' : 'value1', 'key2' : { 'level2_dict' : { 'key1' : 'value3', 'key2' : ['list1','list2','list3','list4'], } } }, 'level1_dict_2' : { 'key1' : 'value1', 'key2' : 'value2', }, } 

Очень упрощенная (и без применения бизнес-логики) я в основном хочу сделать следующее:

 with open("example.py","w") as outfile: example = __import__('example') # Import module example.sample['level1_dict_1']['key2']['level2_dict']['key2'][2] = "newlistitem3" # Change 1 property in a list nested a few levels deep outfile.write("sample = \n" + pprint.pformat(example.sample)) # 

Я хотел бы иметь такое же форматирование, как и исходный файл, но pprint, хотя и читаемый, имеет другое форматирование, чем я бы предпочел. Это может быть как можно ближе к тому, что мне нужно.

вывод на печать:

 sample = {'level1_dict_1': {'key1': 'value1', 'key2': {'level2_dict': {'key1': 'value3', 'key2': ['list1', 'list2', 'newlistitem3', 'list4']}}}, 'level1_dict_2': {'key1': 'value1', 'key2': 'value2'}} 

EDITS & Clarifications: – Моя цель – загрузить модуль, изменить его и сохранить его как исполняемый файл python. Именно по этой причине я возражаю против рассола, json и т. Д. Мне нужно создать один исполняемый файл py. – Пересмотренный вариант использования для пояснения – Добавлены примеры и дополнительная информация о том, что я пробовал

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

Если вы просто хотите получить исходный исходный код модуля, это легко. Например, вы можете использовать inspect.getsource , а затем записать результирующую строку в файл. Или просто используйте inspect.getfile и скопируйте полученный результирующий путь.

И вы можете, конечно, изменить исходный источник при его копировании. Например:

 source = inspect.getsource(foo) with open('newfoo.py', 'wb') as f: f.write(source) f.write('spam = Spam(3)\neggs = Eggs(spam)\n') 

Но вы не можете изменить foo а затем повторно сгенерировать его источник.


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

  • Используйте JSON, pickle (режим 0), YAML и т. Д. Несмотря на то, что вы утверждаете, это структурированные, читаемые текстовые форматы, как и источник Python.

  • Используйте repr . Для строковых, числовых и встроенных констант литералов, а также списков и dicts, содержащих только (рекурсивно) вышеупомянутые типы, repr является round-trippable. Например:


 with open('newfoo.py', 'wb') as f: for name, value in foo.__dict__.items(): f.write('{} = {!r}\n'.format(name, value)) 
  • Если вы уверены, что все ваши ценности являются работоспособными, но не являются положительными, существует множество способов проверить или дезинформировать ваш результат перед его записью. Например:

 with open('newfoo.py', 'wb') as f: for name, value in foo.__dict__.items(): if ast.literal_eval(repr(value)) != value: raise ValueError('Tried to save {}'.format(value)) f.write('{} = {!r}\n'.format(name, value)) 
  • Создавайте файлы данных в хорошем формате, который идеально подходит для генератора кода, читателей и т. Д. Вместо того, чтобы пытаться генерировать источник Python, а затем писать простой код Python, который считывает файлы данных и генерирует объекты во время выполнения.