python - 使用 Django session 中间件进行垃圾收集

标签 python django garbage-collection weak-references django-sessions

注意:抱歉,但我没有达到发布两个以上链接所需的声誉分数。下面发布的片段引用了以下内容 views及配套类'__del__() method

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

    # 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)

在稍后的 View 中访问 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

我最初曾考虑过覆盖 __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)

我的问题是为什么我的类(class)是'__del__()尽管将实际对象存储在 session 中,但在第一个 View 和第二个 View 之间执行的方法?

我尝试使用带有自定义__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()

产生我期望的输出,调用 __del__()仅在退出第二个函数 f2() 后才使用该方法.

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

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

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

感谢您的见解。我已经解决了这个问题,但我仍然很好奇为什么会发生这种行为。

最佳答案

当不再有对象的引用时,将调用

__del__ 方法。这正是请求结束后对象所处的状态:内存中不再有对其的引用。数据库行中有一个引用存储您的 session 信息,但 Python 并不关心这一点,因为它当然不应该关心:它关心的只是您的 View 函数完成后,您的对象超出范围,并被垃圾收集。

当然,在您的测试函数中,您在函数结束后确实有一个对对象的引用:在您的 cache 字典中。但这与存储在 session 中根本不是一回事。

换句话说,这是错误的处理方式。您必须在构建形状的方法中实现清理代码。 (在 session 中存储文件也是一件奇怪的事情,但让我们暂时保留它。)

关于python - 使用 Django session 中间件进行垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16406093/

相关文章:

python - 结合 shell 和 python 代码

python - 如何在 django 中获取内连接的表别名

python - UnicodeDecodeError 与 Django 的 request.FILES

c++ - C++中如何同时使用自动引用计数和虚函数?

.net - 从 .NET 中的构造函数中抛出异常

java - 对 Java 的垃圾收集器如何工作的困惑(节点 + 队列)

python - 正则表达式问题求助

python - 我很难在 python 中使用 mincemeat 进行 mapreduce 来计算不同文件的字数

c++ - 需要帮助使用 C++ 模块扩展 Python 3.2

python - 特定语言环境的gettext