我有一個 Django 應用程式,在管理員中有一個視圖,允許員工用戶上傳一個 csv,然后將其傳遞給一個腳本,該腳本從資料中構建和更新資料庫中的專案。視圖在新執行緒中運行腳本,然后回傳“上傳開始”成功訊息。
應用程式/產品/admin.py
from threading import Thread
# ...
from apps.products.scripts import update_products_from_csv
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# normal ModelAdmin stuff
def upload_csv(self, request):
if request.method == 'POST':
csv_file = request.FILES['csv_file']
t = Thread(target=update_products_from_csv.run, args=[csv_file])
t.start()
messages.success(request, 'Upload started')
return HttpResponseRedirect(reverse('admin:products_product_changelist'))
應用程式/產品/腳本/update_products_from_csv.py
import csv
import threading
from time import time
# ...
def run(upload_file):
# print statements just here for debugging
print('Update script running', threading.currentThread())
start_time = time()
print(start_time)
decoded_file = upload_file.read().decode('utf-8').splitlines()
csv_data = [d for d in csv.DictReader(decoded_file)]
print(len(csv_data))
for i, row in enumerate(csv_data):
if i % 500 == 0:
print(i, time() - start_time)
# code that checks if item needs to be created or updated and logs accordingly
print('Finished', time() - start_time)
在開發中,這作業正常。“上傳開始”訊息幾乎立即出現在瀏覽器中,并在控制臺中列印它在 Thread-3 或 Thread-5 或其他任何東西上啟動,然后執行所有其他列印陳述句。完成后,我可以查詢 EntryLog 模型并確認它進行了更改。
當我將它推送到 Heroku 時,我仍然會立即在瀏覽器中收到“上傳開始”訊息,但是當我查看日志時,它列印的是 Thread-1 而不是 Thread-[任何其他數字]。之后我看到 start_time 列印陳述句執行,但之后回應開始并且沒有其他列印陳述句運行。過了一會兒,我查詢了 EntryLog 模型,但沒有進行任何更改。
從我讀過的內容來看,聽起來我應該能夠像在本地一樣在 Heroku 上使用執行緒,但似乎它是在主執行緒中執行腳本,然后在回應開始時默默地殺死它。
uj5u.com熱心網友回復:
事實證明 Heroku 實際上打開了一個新執行緒就好了。當我打電話時它顯示 Thread-1print(threading.currentThread())是一條紅鯡魚。在我的開發環境 (Windows) 中,生成的執行緒總是列印 Thread-[number 大于 1],但是使用我確信執行完成的簡單執行緒的進一步測驗總是在 Heroku 環境中列印 Thread-1。Windows 與 Linux 上的庫功能可能存在差異?(這是我第一次使用執行緒庫,如果我遺漏了一些明顯的東西,請道歉。)
實際問題似乎是我正在閱讀 csv 檔案的地方。很多列印陳述句后來我將其縮小到所有停止運行的確切行。我嘗試了一個簡單的測驗,只是在一個新執行緒中讀取一個 txt 檔案并得到了相同的結果。沒有拋出任何錯誤或任何東西,在那之后什么也沒有。我將讀取和解碼檔案的代碼移動到主執行緒的視圖中,然后將提取的資料傳遞給新執行緒,然后一切正常。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/410824.html
標籤:
