使用Django的会话中间件进行垃圾收集

时间:2021-01-09 14:21:22

NOTE: Sorry, but I don't have the required reputation score to post more then two links. The snippets posted below reference the following views and supporting class' __del__() method.

注意:抱歉,但我没有必要的声誉分数来发布超过两个链接。下面发布的片段引用了以下视图和支持类'__del __()方法。

I have a function-based view in Django that stores an instance of a class as a value of a django session.

我在Django中有一个基于函数的视图,它将类的实例存储为django会话的值。

    # First view Function
    if request.method == 'POST':
        logger.info('User %s Began Upload of File %s' % (request.user.username, request.FILES['file']))
        form = uploadFileForm1(request.POST, request.FILES)
        if form.is_valid():
            # form.cleaned_data contains an in memory version of the uploaded file.
            uploaded_shp = ShpUploader(form.cleaned_data['file'])
            # Store ShpUploader instance in cookie to be referenced
            request.session['uploaded_shp'] = uploaded_shp
            return HttpResponseRedirect('./2')
        else:
            for uploadfile_error in form.errors['file']:
                logger.warning(uploadfile_error)

The session is accessed in a later view, where I some methods of this object stored inside the session.

在稍后的视图中访问会话,其中我将此对象的一些方法存储在会话中。

    # Second view Function
    if request.method == 'POST':
        # Required to repass shpPath kwarg
        form = uploadFileForm2(request.POST,shpPath=request.session['uploaded_shp'].upload_full_path)
        if form.is_valid():
            # Pass user-defined field mappings to import_shapefile method.
            request.session['uploaded_shp'].import_shapefile(form.cleaned_data)
            logger.info('Successful - User %s Uploaded File %s' % (request.user.username, request.session['uploaded_shp'].upload_full_path))
            return HttpResponseRedirect('./success')
        else:
            print form.errors

I had initially toyed with the idea of overriding the __del__() method in my class, to automatically delete a folder which this object references.

我最初玩弄了在我的类中覆盖__del __()方法的想法,以自动删除该对象引用的文件夹。

# Inside my class definition
def __del__(self):
    """
    Given a directory, remove it an its contents.
    Intended to clean up temporary files after upload.
    """
    shutil.rmtree(self.upload_dir)
    logger.info('Delete Successful: %s' % self.upload_dir)

My question is why is my class' __del__() method executed between the first view and the second view, despite storing the actual object inside a session?

我的问题是为什么我的类'__del __()方法在第一个视图和第二个视图之间执行,尽管将实际对象存储在会话中?

I tried to write a basic example using a class with a custom __del__() method, that uses a dictionary to persist an object between functions. This example:

我尝试使用带有自定义__del __()方法的类编写一个基本示例,该方法使用字典在函数之间保留对象。这个例子:

class tester(object):
    def __init__(self, val):
        self.val = val
        print 'created in %s' % self.val

    def __del__(self):
        print 'deleted'

cache = {} 

def f1():
    print 'in f1'
    t = tester('Test Object Value')
    cache['tdict'] = t
    print cache['tdict'].val

def f2():
    print 'in f2'
    print cache['tdict'].val

if __name__ == '__main__': 
    f1()
    f2()

Produces the out put I would have expected, calling the __del__() method only after exiting the second function f2().

产生我想要的输出,只有在退出第二个函数f2()后调用__del __()方法。

in f1
created in Test Object Value
Test Object Value
in f2
Test Object Value
deleted
[Finished in 0.1s]

Am I missing something in regards to how the session middleware works? One thought I had was in regards to weak references, and if the django session middleware uses these? See below for article link to weak references.

我是否遗漏了有关会话中间件如何工作的内容?我有一个想法是关于弱引用,如果django会话中间件使用这些?请参阅下面的文章链接到弱引用。

# Can't post over two links yet.
http://mindtrove.info/python-weak-references/

Thanks for your insight. I've moved on past this issue, but I'm still curious as to why this behavior is occuring.

感谢您的见解。我已经过了这个问题,但我仍然很好奇为什么会出现这种情况。

1 个解决方案

#1


1  

__del__ methods are called when there are no more references to an object. And that is exactly the state that your object is in after the end of a request: there are no more references to it in memory. There is a reference in the database row that stores your session information, but Python doesn't care about that, as of course it shouldn't: all it cares about is that as soon as your view function finishes, your object goes out of scope, and is garbage collected.

当没有对对象的更多引用时,将调用__del__方法。这正是您的对象在请求结束后所处的状态:在内存中没有更多对它的引用。在数据库行中有一个存储会话信息的引用,但Python并不关心它,当然它不应该:它只关心的是,只要你的视图函数完成,你的对象就会消失。范围,并且是垃圾收集。

In your test function, of course, you do have a reference to your object after the end of the function: in your cache dictionary. But that's not the same thing at all as storing in the session.

当然,在测试函数中,在函数结束后确实有对象的引用:在缓存字典中。但这与存储在会话中完全不同。

In other words, this is the wrong way to be going about this. You'll have to implement the clean-up code in the method that builds the shapes. (Storing a file in a session is also a strange thing to do, but let's leave that for now.)

换句话说,这是错误的做法。您必须在构建形状的方法中实现清理代码。 (在会话中存储文件也是一件很奇怪的事情,但现在让我们离开。)

#1


1  

__del__ methods are called when there are no more references to an object. And that is exactly the state that your object is in after the end of a request: there are no more references to it in memory. There is a reference in the database row that stores your session information, but Python doesn't care about that, as of course it shouldn't: all it cares about is that as soon as your view function finishes, your object goes out of scope, and is garbage collected.

当没有对对象的更多引用时,将调用__del__方法。这正是您的对象在请求结束后所处的状态:在内存中没有更多对它的引用。在数据库行中有一个存储会话信息的引用,但Python并不关心它,当然它不应该:它只关心的是,只要你的视图函数完成,你的对象就会消失。范围,并且是垃圾收集。

In your test function, of course, you do have a reference to your object after the end of the function: in your cache dictionary. But that's not the same thing at all as storing in the session.

当然,在测试函数中,在函数结束后确实有对象的引用:在缓存字典中。但这与存储在会话中完全不同。

In other words, this is the wrong way to be going about this. You'll have to implement the clean-up code in the method that builds the shapes. (Storing a file in a session is also a strange thing to do, but let's leave that for now.)

换句话说,这是错误的做法。您必须在构建形状的方法中实现清理代码。 (在会话中存储文件也是一件很奇怪的事情,但现在让我们离开。)