Python: мариновать местных жителей (), или у местных жителей есть более легкий кузен - PullRequest
1 голос
/ 26 июля 2011

Я работаю в Джанго. В Django при рендеринге шаблона вы отправляете ему контекстный словарь для замены. Поскольку я ленивый / СУХОЙ, я часто использую locals () в качестве ярлыка вместо отправки словаря, который выглядит как {'my_var': my_var, 'var2': var2}.

Обычно это прекрасно работает и экономит много ошеломляющих повторений.

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

Однако проблема в том, что django-уведомления извлекают контекстный словарь во время очереди. Вот где трюк locals () терпит неудачу - словарь от местных жителей имеет МНОГО дерьма, кроме локальных переменных (например, он имеет import и int ()). Словарь, созданный местными жителями, не зародился.

Я вижу три варианта: 1) переписать метод очередей django-уведомлений для рендеринга шаблона перед его сохранением (просто, но немного утомительно и нарушает возможность обновления) 2) прекратить использовать трюк с местными жителями и начать повторяться 3) Попробуйте найти облегченную версию местных жителей (или способ засолки местных жителей).

Я надеюсь, что кто-то ведет в направлении №3.

В случае, если это может быть уместно, вот ошибка, которую я получаю, когда пытаюсь перебрать с помощью ярлыка locals ():

TypeError: can't pickle ellipsis objects

Далее вывод словаря locals ():

{
    '__builtins__': 
    {
        'bytearray': <type 'bytearray'>,
         'IndexError': <type 'exceptions.IndexError'>,
         'all': <built-in function all>,
         'help': Type help() for interactive help,
         or help(object) for help about object.,
         'vars': <built-in function vars>,
         'SyntaxError': <type 'exceptions.SyntaxError'>,
         'unicode': <type 'unicode'>,
         'UnicodeDecodeError': <type 'exceptions.UnicodeDecodeError'>,
         'isinstance': <built-in function isinstance>,
         'copyright': Copyright (c) 2001-2010 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum,
         Amsterdam.
All Rights Reserved.,
         'NameError': <type 'exceptions.NameError'>,
         'BytesWarning': <type 'exceptions.BytesWarning'>,
         'dict': <type 'dict'>,
         'input': <built-in function input>,
         'oct': <built-in function oct>,
         'bin': <built-in function bin>,
         'SystemExit': <type 'exceptions.SystemExit'>,
         'StandardError': <type 'exceptions.StandardError'>,
         'format': <built-in function format>,
         'repr': <built-in function repr>,
         'sorted': <built-in function sorted>,
         'False': False,
         'RuntimeWarning': <type 'exceptions.RuntimeWarning'>,
         'list': <type 'list'>,
         'iter': <built-in function iter>,
         'reload': <built-in function reload>,
         'Warning': <type 'exceptions.Warning'>,
         '__package__': None,
         'round': <built-in function round>,
         'dir': <built-in function dir>,
         'cmp': <built-in function cmp>,
         'set': <type 'set'>,
         'bytes': <type 'str'>,
         'reduce': <built-in function reduce>,
         'intern': <built-in function intern>,
         'issubclass': <built-in function issubclass>,
         'Ellipsis': Ellipsis,
         'EOFError': <type 'exceptions.EOFError'>,
         'locals': <built-in function locals>,
         'BufferError': <type 'exceptions.BufferError'>,
         'slice': <type 'slice'>,
         'FloatingPointError': <type 'exceptions.FloatingPointError'>,
         'sum': <built-in function sum>,
         'getattr': <built-in function getattr>,
         'abs': <built-in function abs>,
         'exit': Use exit() or Ctrl-D (i.e. EOF) to exit,
         'print': <built-in function print>,
         'True': True,
         'FutureWarning': <type 'exceptions.FutureWarning'>,
         'ImportWarning': <type 'exceptions.ImportWarning'>,
         'None': None,
         'hash': <built-in function hash>,
         'ReferenceError': <type 'exceptions.ReferenceError'>,
         'len': <built-in function len>,
         'credits':     Thanks to CWI,
         CNRI,
         BeOpen.com,
         Zope Corporation and a cast of thousands
    for supporting Python development.  See www.python.org for more information.,
         'frozenset': <type 'frozenset'>,
         '__name__': '__builtin__',
         'ord': <built-in function ord>,
         'super': <type 'super'>,
         '_': None,
         'TypeError': <type 'exceptions.TypeError'>,
         'license': Type license() to see the full license text,
         'KeyboardInterrupt': <type 'exceptions.KeyboardInterrupt'>,
         'UserWarning': <type 'exceptions.UserWarning'>,
         'filter': <built-in function filter>,
         'range': <built-in function range>,
         'staticmethod': <type 'staticmethod'>,
         'SystemError': <type 'exceptions.SystemError'>,
         'BaseException': <type 'exceptions.BaseException'>,
         'pow': <built-in function pow>,
         'RuntimeError': <type 'exceptions.RuntimeError'>,
         'float': <type 'float'>,
         'MemoryError': <type 'exceptions.MemoryError'>,
         'StopIteration': <type 'exceptions.StopIteration'>,
         'globals': <built-in function globals>,
         'divmod': <built-in function divmod>,
         'enumerate': <type 'enumerate'>,
         'apply': <built-in function apply>,
         'LookupError': <type 'exceptions.LookupError'>,
         'open': <built-in function open>,
         'quit': Use quit() or Ctrl-D (i.e. EOF) to exit,
         'basestring': <type 'basestring'>,
         'UnicodeError': <type 'exceptions.UnicodeError'>,
         'zip': <built-in function zip>,
         'hex': <built-in function hex>,
         'long': <type 'long'>,
         'next': <built-in function next>,
         'ImportError': <type 'exceptions.ImportError'>,
         'chr': <built-in function chr>,
         'xrange': <type 'xrange'>,
         'type': <type 'type'>,
         '__doc__': "Built-in functions,
         exceptions,
         and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.",
         'Exception': <type 'exceptions.Exception'>,
         'tuple': <type 'tuple'>,
         'UnicodeTranslateError': <type 'exceptions.UnicodeTranslateError'>,
         'reversed': <type 'reversed'>,
         'UnicodeEncodeError': <type 'exceptions.UnicodeEncodeError'>,
         'IOError': <type 'exceptions.IOError'>,
         'hasattr': <built-in function hasattr>,
         'delattr': <built-in function delattr>,
         'setattr': <built-in function setattr>,
         'raw_input': <built-in function raw_input>,
         'SyntaxWarning': <type 'exceptions.SyntaxWarning'>,
         'compile': <built-in function compile>,
         'ArithmeticError': <type 'exceptions.ArithmeticError'>,
         'str': <type 'str'>,
         'property': <type 'property'>,
         'GeneratorExit': <type 'exceptions.GeneratorExit'>,
         'int': <type 'int'>,
         '__import__': <built-in function __import__>,
         'KeyError': <type 'exceptions.KeyError'>,
         'coerce': <built-in function coerce>,
         'PendingDeprecationWarning': <type 'exceptions.PendingDeprecationWarning'>,
         'file': <type 'file'>,
         'EnvironmentError': <type 'exceptions.EnvironmentError'>,
         'unichr': <built-in function unichr>,
         'id': <built-in function id>,
         'OSError': <type 'exceptions.OSError'>,
         'DeprecationWarning': <type 'exceptions.DeprecationWarning'>,
         'min': <built-in function min>,
         'UnicodeWarning': <type 'exceptions.UnicodeWarning'>,
         'execfile': <built-in function execfile>,
         'any': <built-in function any>,
         'complex': <type 'complex'>,
         'bool': <type 'bool'>,
         'ValueError': <type 'exceptions.ValueError'>,
         'NotImplemented': NotImplemented,
         'map': <built-in function map>,
         'buffer': <type 'buffer'>,
         'max': <built-in function max>,
         'object': <type 'object'>,
         'TabError': <type 'exceptions.TabError'>,
         'callable': <built-in function callable>,
         'ZeroDivisionError': <type 'exceptions.ZeroDivisionError'>,
         'eval': <built-in function eval>,
         '__debug__': True,
         'IndentationError': <type 'exceptions.IndentationError'>,
         'AssertionError': <type 'exceptions.AssertionError'>,
         'classmethod': <type 'classmethod'>,
         'UnboundLocalError': <type 'exceptions.UnboundLocalError'>,
         'NotImplementedError': <type 'exceptions.NotImplementedError'>,
         'AttributeError': <type 'exceptions.AttributeError'>,
         'OverflowError': <type 'exceptions.OverflowError'>
    },
     'notification': <module 'notification.models' from '/home/b/webapps/myapp/notification/models.pyc'>,
     'u': <User: abcd>,
     'User': <class 'django.contrib.auth.models.User'>
}

Ответы [ 4 ]

2 голосов
/ 26 июля 2011

Пожалуйста, позвольте мне предложить альтернативу использованию locals()

class Object(object):
    pass

def foo():
    result = Object()
    result.my_var = 'bar'
    your_var = 'not to be returned'
    result.var2 = 'baz' + result.my_var + len(your_var)
    return result.__dict__

Другой вариант - добавить объекты в контекст по мере их создания.

def foo():
    result = {}
    result['my_var'] = my_var = 'bar'
    your_var = 'not to be returned'
    result['var2'] = var2 = 'baz' + my_var + len(your_var)
    return result

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

edit: Вы должны использовать эту вторую версию. Я уверен, что дополнительные нажатия клавиш при использовании context dict (result или ctx или что-то еще) не делают ' Я чувствую себя очень сухо, но позвольте мне сказать вам, что это на самом деле хорошо. Zen of Python заявляет «Явное лучше, чем неявное». Когда вы возвращаете значение locals(), вы возвращаетесь, кто знает, что. Все, что было в глобальном пространстве имен, все, что находится во вложенном пространстве имен, все промежуточные вычисления, которые вы, возможно, сделали, все эти вещи неявно возвращаются вызывающей стороне.

Если вы создаете контейнер для значения, которое хотите вернуть, вы явно указываете свое намерение, рисуя резкую линию между

this_is_for_me = 'foo'

и

result['this_is_for_you'] = 'bar'

Различие ясно в коде, что является общедоступным для использования другими; и частная, может быть изменена, зависит от реализации. Для звонящего это также понятно, потому что эти частные значения просто недоступны.

И если вы интегрируете внешнюю библиотеку, которая тем не менее использует locals() magic, вы должны быть очень нерешительными относительно того, где и как вы ее используете. Я, вероятно, предпочел бы patch код, который делает это, по сравнению с любой другой доступной опцией.

0 голосов
/ 14 октября 2013

В вашем фрагменте кода из locals() я не вижу ничего такого, что нельзя было бы "протравить" с помощью укроп .Укроп может сериализовать практически все в Python, а также имеет несколько хороших инструментов , которые помогут вам понять, что вызывает сбой в процессах консервирования при сбое кода.Пока django использует pickle, а не cPickle, все, что вам нужно сделать для расширения pickle для сериализации таких вещей, как EllipsisType, это:

>>> import dill
>>> # this will enable python's pickle to pickle almost everything dill can pickle
>>> 
>>> # on the full set of dill's types, this usually works unless there's a generator
>>> # or an interator-type or something odd like a traceback object in locals
>>> dill.loads(dill.dumps(locals()))
>>> ...
>>> # if you get a pickling error, use dill's tools to figure out a workaround
>>> dill.detect.badobjects(your_bad_object, depth=0)
>>> dill.detect.badobjects(your_bad_object, depth=1)
>>> ...

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

0 голосов
/ 05 августа 2011

Нет.Стоит повторить, если вы собираетесь мариновать.Многие объекты, некоторые из которых не являются интуитивно понятными, не могут быть обработаны (т. Е. Ввод формы).

Ярлык localals () следует использовать только в том случае, если вы уверены, что шаблон будет отображен немедленно.

0 голосов
/ 26 июля 2011

Вы, вероятно, можете хранить все, что есть в локальных файлах, кроме глобальных.

...