2009-10-16 4 views
2

(Предположим, что: время запуска приложения абсолютно критично, мое приложение запущено много, мое приложение работает в среде, в которой импорт медленнее, чем обычно, необходимо импортировать много файлов, а компиляция в файлы .pyc - это недоступно.)Как объединить несколько исходных файлов Python в один файл?

Я хотел бы объединить все исходные файлы Python, которые определяют набор модулей в один новый исходный файл Python.

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

Возможно ли это?

Это грубое ручное моделирование того, что может произвести инструмент при подаче исходных файлов для модулей «bar» и «baz». Вы должны запустить такой инструмент до развертывания кода.

__file__ = 'foo.py' 

def _module(_name): 
    import types 
    mod = types.ModuleType(name) 
    mod.__file__ = __file__ 
    sys.modules[module_name] = mod 
    return mod 

def _bar_module(): 

    def hello(): 
     print 'Hello World! BAR' 

    mod = create_module('foo.bar') 
    mod.hello = hello 
    return mod 

bar = _bar_module() 
del _bar_module 

def _baz_module(): 

    def hello(): 
     print 'Hello World! BAZ' 

    mod = create_module('foo.bar.baz') 
    mod.hello = hello 
    return mod 

baz = _baz_module() 
del _baz_module 

И теперь вы можете:

from foo.bar import hello 
hello() 

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

Это очень схожая идея с инструментами, используемыми для сборки и оптимизации файлов JavaScript перед отправкой в ​​браузер, где задержка нескольких HTTP-запросов вредит производительности. В этом случае Python это задержка импорта сотен исходных файлов Python при запуске, который болит.

+6

Есть ли у вас цифры, которые доказывают, что это повлияет на время запуска интерпретатора? –

+0

Время запуска - определенно проблема. Я надеюсь, что это ускорит ситуацию. Я уточнил ограничения в вопросе. –

+1

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

ответ

1

Я думаю, что из-за предварительной компиляции файлов Python и некоторого системного кэширования скорость, которую вы в конечном итоге получите, не будет измерима.

+0

Вы имели в виду, что «не будет измеримым»? –

+0

Предварительная компиляция в .pyc-файлы недоступна. Кэширование не так хорошо, как я надеюсь, в этой конкретной ситуации. Я уточнил это в вопросе. –

+0

Да, конечно, «не будет измеримым» :) –

3

Если это на Google App Engine, как теги показывают, убедитесь, что вы используете эту идиому

def main(): 
    #do stuff 
if __name__ == '__main__': 
    main() 

Поскольку GAE не перезапустить приложение каждый запрос, если .py не изменилось, она просто работает main().

Этот трюк позволяет писать CGI-приложения в стиле без троганий ударили

AppCaching

Если скрипт обработчика обеспечивает основную() рутины, среда выполнения также кэшей сценария. В противном случае скрипт обработчика загружается для каждого запроса .

+0

Спасибо, но я уже это делаю. Обратите внимание, что механизм приложения часто кэшируется всего лишь секунду или около того, давая 14 000 или около того возможностей кэшировать пропуски каждый день, что усугубляется при использовании многих модулей со сложными зависимостями импорта. Я действительно заинтересован в максимальной производительности запуска. –

0

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

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

+0

Я не жертвуя всей модульности, потому что я предлагаю обработать исходный код с помощью инструмента до развертывания, очень в том смысле, что современные инструменты javascript объединяют, разделяют и оптимизируют javascript перед развертыванием этого фактического браузера. Это хорошая идея сказать «напишите свой код, чтобы импортировать только то, что вам нужно», но затем это исключает использование исходных файлов 300 od в основном django, не включая модули Contrib, внешние библиотеки и все, что я могу написать. Кроме того, вы часто хотите импортировать много кода, потому что вы действительно используете его. –

+0

Ник, вы работаете в Google, можете ли вы описать процесс загрузки кода пользователя на App Engine, пожалуйста? Это не просто стоимость диска, поскольку загружаются несколько модулей, как в обычной настройке, потому что весь код пользователя не разворачивается ко всем экземплярам одновременно. Как это делается? Как это делается? Все ли файлы развернуты вместе, по одному или по партиям? Как работает пользовательский почтовый индекс? когда вы загружаете один модуль из zip, все модули загружены, или это происходит по требованию? и т. д. –

+0

Если наличие исходных файлов «300 нечетных» является проблемой для импорта по требованию, одинаково проблематично, если вы хотите объединить их все - либо потребует существенных изменений. Проблема с использованием большой структуры, такой как Django, заключается в том, что, как вы заметили, для импорта требуется много времени. Я сомневаюсь, что вы используете более 20% модулей для любого данного запроса. –

0

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

Я бы сделал список всех моих модулей, например. my_files = ['foo', 'bar', 'baz']

Я бы затем использовать os.path утилиту, чтобы прочитать все строки во всех файлах в директории источника и записываю их все в новый файл, фильтруя все import foo|bar|baz линий, поскольку весь код теперь в пределах одного файла.

Проклятие, наконец, добавление main() от __init__.py (если есть) в хвосте файла.

 Смежные вопросы

  • Нет связанных вопросов^_^