2012-08-06 247 views
3

我正在使用Django來讀取ajax上傳的文件以將其存儲在模型中。上傳請求包含原始上傳的圖像數據。在Python中,在使用read()之後,我需要使用close()嗎?

def my_view(request): 
    upload = request 
    model_instance.image_field.save(uniquename, ContentFile(upload.read())) 

如果有關係,我使用AmazonS3作爲我上傳文件的存儲後端。

在包含此代碼的函數中,有一處存在內存泄漏。

這樣做後,我需要撥打upload.close()來釋放資源/內存嗎?
或者是我的內存問題來自其他問題,在這個函數的其他地方?

+0

我原以爲AJAX會使用「POST」,或者Django會將它解釋爲多部分形式...... – 2012-08-06 18:36:26

+0

嗯,這是一個POST請求。如果我發佈了整個視圖,您會看到我已經檢查了函數定義和相關代碼之間的請求方法。但是因爲我問的問題似乎並不重要,我沒有包括它。 – 2012-08-06 18:45:20

回答

15

python垃圾收集器將在文件不再被引用時關閉文件。

如果您的upload變量是一個函數中的局部變量,它將在函數返回時被清除。因此,文件upload將在正常垃圾回收週期中自動關閉。

也就是說,關閉文件可能會更好。您可以使用該文件爲context manager,它會自動關閉時的上下文中退出:

with open('yourfilepath.ext') as upload: 
    model_instance.image_field.save(uniquename, ContentFile(upload.read())) 

如果upload東西Django的產生對你來說,開放和準備好了,你仍然可以把它與自動關閉在contextlib.closing decorator

import contextlib 
with contextlib.closing(upload): 
    model_instance.image_field.save(uniquename, ContentFile(upload.read())) 

要回答你的問題的其餘部分:你的泄漏是最有可能在其他地方。

+0

+1對於上下文管理器 - 值得注意的是,雖然CPython的GC將關閉超出範圍和未引用的文件對象,但其他實現可能不會 - 也就是垃圾收集不可預測每個週期等... – 2012-08-06 18:30:32

+0

我意識到我的帖子被省略上傳變量提及的關鍵細節以及它如何設置。我做了一些編輯以表明它實際上與代碼描述的情況稍有不同。無論如何,我感謝您花時間來解決我的問題,並且很高興知道我的泄漏很可能在其他地方。 – 2012-08-06 18:35:19

+0

@ClayWardell:和我的'contextlib.closing'示例不包含你的用例? – 2012-08-06 18:37:35

相關問題