Django / Python импортирует производительность - PullRequest
1 голос
/ 24 сентября 2010

Может кто-нибудь доказать, почему это плохая практика, использовать такое решение:

В просмотрах Django в 98% случаев вам нужно использовать

  from django.http import HttpResponseRedirect
  from django.core.urlresolvers import reverse
  from django.utils.translation import ugettext as _

в любом случае, в моем проекте каждое представление имеет импорт, и все используется почти в каждой второй функции представления:

from datetime import datetime
from django.conf import settings
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.core import paginator
from django.db import connection
from django.db.models import Q
from django.http import HttpResponseRedirect, Http404, HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.utils.translation import ugettext as _

Теперь добавьте несколько моделей и форм, и у меня есть 50 строк чушь, которые невозможно прочитать вообще.

Первое, что пришло мне в голову, это, конечно, сделать больше представлений, разделить некоторые операции и т. Д. И т. П., Но все еще около 30 строк импорта уничтожают мою ориентацию в коде.

Тогда я просто решил поместить все, что используется в представлениях, в 95% случаев в каталог /project/app/imports/view.py. Теперь у меня есть все обычные вещи только с импортом ONE , но мой коллега напал на меня, что очень трудно читать этот вид кода, потому что вы не можете видеть, что импортируется, и какого черта это так сложно открыть еще одну вкладку в вашей IDE .. ??? [особенно это касается пользователей vim, у них есть FRAMES, и он использует vim]

Я сделал то же самое с моделями, у моих моделей есть свой собственный каталог, потому что их там более 50, и эти файлы не маленькие - около 150 строк в каждом .. Даже в этих файлах мало моделей ... так что я я просто делаю что-то вроде:

from myapp.models.mymodel import *

и есть несколько мест, где я просто делаю: from myapp.models import * [ init .py из myapp / import dir находится здесь]

Проблемы:

1) хорошо, так что первая проблема - это пространство имен, такой импорт моделей может быть действительно смешным ... но решение с представлениями и формами - это всего лишь легкость открыть еще одну вкладку в вашей IDE

2) проблема с производительностью? мой коллега действительно много спорит с этим аргументом, что «каждый импорт занимает 256 КБ оперативной памяти» ?? (запустив скомпилированный файл .pyc? нет, я в это не верю;)

На самом деле речь идет о проблеме производительности из-за импорта.

p.s. Я действительно новичок в Python (всего 3 месяца), и я открыт для объективных аргументов для всех за и против этого решения.

UPDATE

Однажды я задал вопрос о том, как перенести импорт в автономный файл, чтобы никто не жаловался на это =) вопрос здесь

Ответы [ 3 ]

5 голосов
/ 24 сентября 2010

1) лень не добавлять префикс импортированных имен к модулю, из которого они получены.Это не что иное, как лень не желать прокручивать информацию об импорте в код.Как именно эта путаница импорта в другом файле облегчает чтение?Я бы оставил это в оригинальном файле, где они на самом деле используются.Это улучшает удобочитаемость, потому что если мне нужно знать, откуда что-то, то я могу просто перейти к началу файла и проверить его (используя кольцо меток emacs, чтобы вернуться назад).Это также упрощает ведение списка, потому что мне просто нужно выполнить быстрый поиск, чтобы увидеть, где что-то используется (или не используется).

2) На моем компьютере для импорта файла требуется ~ 812 микросекундмодуль.

$ python -mtimeit -s'import os' 'reload(os)'
1000 loops, best of 3: 808 usec per loop

Это, конечно, сильно зависит от того, где находится ваша PYTHONPATH.Если производительность настолько низка, вы можете выжать немного, подтасовав это.YMMV.

Я не уверен, откуда ваш коллега получает 256 КБ.Это будет зависеть от размера задействованных объектов кода.

>>> import sys
>>> sys.getsizeof(sys)
24
>>> sys.getsizeof(sys.modules['__main__'])
24

Как видите, на моем 32-битном компьютере объект модуля занимает всего 24 байта.У меня есть ощущение, что это будет зависеть от системы.

>>> def sizeofmodule(mod):
...     return sum(sys.getsizeof(getattr(mod, o)) for o in dir(mod))
... 
>>> sizeofmodule(itertools)
8662
>>> sizeofmodule(sys)
10275
>>> sizeofmodule(operator)
5230
2 голосов
/ 24 сентября 2010

Имейте в виду, что вы можете импортировать набор подпакетов. Так

from django.conf import settings
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.core import paginator
from django.db import connection
from django.db.models import Q
from django.http import HttpResponseRedirect, Http404, HttpResponse
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.utils.translation import ugettext as _

может стать

from django import conf, contrib, db, http, shortcuts, template, utils
from django.core import urlresolvers, paginator

, что коротко, позволяет избежать написания django везде и оставляет довольно очевидным, откуда исходит что-то вроде urlresolvers.reverse. Это также имеет преимущество, заключающееся в том, что общие имена, такие как reverse, не сопоставляются с очень специфичными функциями, что дает вам более читаемый код.

1 голос
/ 24 сентября 2010

Некоторые моменты для рассмотрения:

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

Каждый импорт , а не занимает 256 КБ памяти.Возможно, каждый отдельный файл, загруженный один раз, есть (хотя я бы тоже сомневался в этом), но повторный импорт одного и того же файла не занимает 256 КБ каждый раз;это просто создание ссылки.Если речь идет об использовании памяти, просто профилируйте ее - загрузите 10000 единиц и посмотрите, сколько памяти используется.

Для модулей Django вам не всегда нужно создавать каталог для каждого;Я импортирую каждый класс модели из models/__init__.py (например, from Customer import Customer), так что я могу сказать from myapp.models import Profile, Customer, Book, ....


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

В то же время я настоятельно рекомендую против того, что некоторые люди могут порекомендовать: import django и затем использовать полные имена модулей.В результате набираются такие вещи, как django.core.urlresolvers.reverse.Когда вы обнаруживаете, что регулярно копируете и вставляете имена функций, потому что они такие длинные, что-то пошло не так.

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

Вы будетевозможно, вы найдете меньше возражений против реакции кишечника, если вы импортируете сам модуль «коллекция модулей» - import djangohelpers или import djangohelpers as dh.Затем вы пишете такие вещи, как dh.paginator.Это дает именам четкую область видимости и позволяет намного легче увидеть, где они используются и откуда поступают конкретные имена функций, которые вы теряете с помощью «import *».

(вы, вероятно, действительно хотите импортироватьтакие вещи, как Q и _ как голые имена.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...