1

注:申し訳ありませんが、2 つ以上のリンクを投稿するために必要な評価スコアがありません。以下に投稿されたスニペットは、次のビューとサポート クラスの__del__() メソッドを参照しています。

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)

セッションは、セッション内に保存されたこのオブジェクトのいくつかのメソッドで、後のビューでアクセスされます。

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

私の質問は、実際のオブジェクトをセッション内に保存しているにもかかわらず、クラスの__del__()メソッドが最初のビューと 2 番目のビューの間で実行されるのはなぜですか?

__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__()2 番目の関数を終了した後にのみメソッドを呼び出して、期待どおりの出力を生成しますf2()

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

セッション ミドルウェアのしくみに関して何か不足していますか? 私が考えていたのは、弱い参照に関するものでした.djangoセッションミドルウェアがこれらを使用している場合は? 弱参照への記事リンクについては、以下を参照してください。

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

あなたの洞察に感謝します。私はこの問題を乗り越えましたが、なぜこの動作が発生しているのかについてはまだ興味があります.

4

1 に答える 1

1

__del__オブジェクトへの参照がなくなると、メソッドが呼び出されます。これはまさに、リクエストの終了後にオブジェクトが置かれている状態です。つまり、メモリ内にオブジェクトへの参照はもうありません。セッション情報を格納するデータベース行に参照があります、Python はそれを気にしません。もちろん、そうすべきではありません。気にするのは、ビュー関数が終了するとすぐにオブジェクトが終了することだけです。ガベージコレクションされます。

もちろん、テスト関数では、関数の終了後にオブジェクトへの参照があります。つまり、cache辞書にあります。しかし、それはセッションに保存することとまったく同じではありません。

言い換えれば、これは間違ったやり方です。シェイプを作成するメソッドにクリーンアップ コードを実装する必要があります。(ファイルをセッションに保存するのも奇妙なことですが、今はそれを残しましょう。)

于 2013-05-06T19:59:50.510 に答える