关闭Django FieldFile

时间:2015-02-21 00:21:43

标签: python django file-io

何时应该从Django FieldFile关闭文件句柄?我试图在每次使用后关闭它,但是第二次尝试从文件中读取时,我收到错误:

  

ValueError:关闭文件的I / O操作

这是一个显示问题的摘录:

# Tested with Django 1.9.2
import os
import sys

import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.core.files.base import ContentFile
from django.db.models.base import ModelBase

NAME = 'udjango'


def main():
    setup()

    class Person(models.Model):
        first_name = models.CharField(max_length=30)
        last_name = models.CharField(max_length=30)
        data_file = models.FileField()

    syncdb(Person)
    if os.path.exists('jimmy.csv'):
        os.remove('jimmy.csv')

    p1 = Person(first_name='Jimmy', last_name='Jones')
    p1.data_file.save('jimmy.csv', ContentFile('Hello,World!'))

    p2 = Person.objects.get(pk=1)

    # This with block will close the file at the end.
    with p2.data_file:
        for line in p2.data_file:
            print '1: ' + line

    # The second time I try to read from the file, it fails.
    with p2.data_file:
        # Next line throws ValueError: I/O operation on closed file
        for line in p2.data_file:
            print '2: ' + line


def setup():
    DB_FILE = NAME + '.db'
    with open(DB_FILE, 'w'):
        pass  # wipe the database
    settings.configure(
        DEBUG=True,
        DATABASES={
            DEFAULT_DB_ALIAS: {
                'ENGINE': 'django.db.backends.sqlite3',
                'NAME': DB_FILE}},
        LOGGING={'version': 1,
                 'disable_existing_loggers': False,
                 'formatters': {
                    'debug': {
                        'format': '%(asctime)s[%(levelname)s]'
                                  '%(name)s.%(funcName)s(): %(message)s',
                        'datefmt': '%Y-%m-%d %H:%M:%S'}},
                 'handlers': {
                    'console': {
                        'level': 'DEBUG',
                        'class': 'logging.StreamHandler',
                        'formatter': 'debug'}},
                 'root': {
                    'handlers': ['console'],
                    'level': 'WARN'},
                 'loggers': {
                    "django.db": {"level": "WARN"}}})
    app_config = AppConfig(NAME, sys.modules['__main__'])
    apps.populate([app_config])
    django.setup()
    original_new_func = ModelBase.__new__

    @staticmethod
    def patched_new(cls, name, bases, attrs):
        if 'Meta' not in attrs:
            class Meta:
                app_label = NAME
            attrs['Meta'] = Meta
        return original_new_func(cls, name, bases, attrs)
    ModelBase.__new__ = patched_new


def syncdb(model):
    """ Standard syncdb expects models to be in reliable locations.

    Based on https://github.com/django/django/blob/1.9.3
    /django/core/management/commands/migrate.py#L285
    """
    connection = connections[DEFAULT_DB_ALIAS]
    with connection.schema_editor() as editor:
        editor.create_model(model)

main()

为了查看with块是否存在问题,我尝试显式关闭该文件,但我得到了完全相同的行为:

    for line in p2.data_file:
        print '1: ' + line
    p2.data_file.close()

    # Next line throws ValueError: I/O operation on closed file
    for line in p2.data_file:
        print '2: ' + line
    p2.data_file.close()

1 个答案:

答案 0 :(得分:1)

似乎我不应该依赖FieldFile对open()的隐式调用。该文件将在第一次自动打开,但不会在您关闭后自动打开。

open()添加显式调用使其有效。

    p2.data_file.open('rU')
    with p2.data_file:
        for line in p2.data_file:
            print '1: ' + line

    p2.data_file.open('rU')
    with p2.data_file:
        for line in p2.data_file:
            print '2: ' + line