RuntimeError: превышена максимальная глубина рекурсии: почему? - PullRequest
0 голосов
/ 27 февраля 2012

Я создал подкласс объекта Django File, чтобы позаботиться об удаленном файле.Я также хотел сделать ленивую версию, создав подкласс RemoteFileLazy класса Lazyobject, но он не работает, как я ожидал.Я получаю ошибку.

import urllib2
from django.core.files.base import File
from django.utils.functional import LazyObject

class RemoteFile(File):

    def __init__(self, url):
        super(RemoteFile, self).__init__(urllib2.urlopen(urllib2.Request(url)))

    def __str__(self):
        return 'Remote content'

    def __nonzero__(self):
        return True

    def open(self, mode=None):
        self.seek(0)

    def close(self):
        pass

    def chunks(self, chunk_size=None):
    # CHUNKS taking care of no known size!
        if not chunk_size:
            chunk_size = self.DEFAULT_CHUNK_SIZE

        if hasattr(self, 'seek'):
            self.seek(0)
        # Assume the pointer is at zero...
        counter = self.size

        while True:
            data = self.read(chunk_size)
            if not data:
                break
            yield data

class RemoteFileLazy(LazyObject):

    def __init__(self, url):
        # # as said in the django code: For some reason, we have to inline LazyObject.__init__ here to avoid
        # recursion
        self._wrapped = None
        self.url = url

    def _setup(self):
        self._wrapped = RemoteFile(self.url)

Когда я запускаю этот код:

rfl = filehelper.RemoteFileLazy(url="http://www.google.fr")

Я получаю эту ошибку:

RuntimeError: maximum recursion depth exceeded

Есть идеи?Я не вызывал LazyObject. init , как это было упомянуто в коде django, хотя ... Я думаю, что "self.url = url" в методе init вызывает эту ошибку, верно?Поэтому я не могу использовать ленивый объект с атрибутами?

Спасибо.

Traceback:

c:\Users\Michael\Dropbox\development\tools\Portable Python 2.7.2.1-django1.3.1\App\lib\site-packages\django\utils\functional.pyc in __getattr__(self, name)
    274     def __getattr__(self, name):
    275         if self._wrapped is None:
--> 276             self._setup()
    277         return getattr(self._wrapped, name)
    278

C:\Users\Michael\Dropbox\development\projects\django-socialdealing\socialdealing\apps\etl\utils\filehelper.py in _setup(self)
     58
     59     def _setup(self):
---> 60         self._wrapped = RemoteFile(self.url)
     61
     62

c:\Users\Michael\Dropbox\development\tools\Portable Python 2.7.2.1-django1.3.1\App\lib\site-packages\django\utils\functional.pyc in __getattr__(self, name)
    274     def __getattr__(self, name):
    275         if self._wrapped is None:
--> 276             self._setup()
    277         return getattr(self._wrapped, name)
    278

1 Ответ

1 голос
/ 27 февраля 2012

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

Чтобы исправить это, замените

self.url = url # this tries to retrieve the wrapped object to set its 'url' attribute

на

self.__dict__['url'] = url # this actually stores an attribute on the LazyObject container.

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

...