尝试在 Heroku 的单独线程中执行 运行 任务,但似乎没有新线程打开
Trying to run task in a separate thread on Heroku, but no new thread seems to open
我有一个 Django 应用程序,在管理员中有一个视图,允许员工用户上传一个 csv,然后将其传递给一个脚本,该脚本根据数据构建和更新数据库中的项目。视图 运行 在新线程中发送脚本,然后 returns 一条“上传开始”成功消息。
apps/products/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'))
apps/products/scripts/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 打印语句执行,但之后响应开始,其他打印语句 none 运行。过了一会儿,我查询了 EntryLog 模型,但没有进行任何更改。
从我读到的内容来看,我应该能够像在本地一样在 Heroku 上使用线程,但它似乎在主线程中执行脚本,然后在响应开始。
原来 Heroku 实际上打开了一个新线程就好了。当我调用 print(threading.currentThread())
时它显示 Thread-1 是一个转移注意力的问题。在我的开发环境 (Windows) 中,生成的线程总是打印 Thread-[number greater than 1],但是在 Heroku 环境中,我确定执行完成的简单线程的进一步测试总是打印 Thread-1。库在 Windows 和 Linux 上的功能可能有所不同? (这是我第一次使用线程库,如有遗漏,请见谅。)
实际问题似乎出在我读取 csv 文件的位置。后来有很多打印语句,我将其缩小到一切都停止的确切行 运行。我尝试了一个简单的测试,只是在一个新线程中读取一个 txt 文件,得到了相同的结果。没有抛出任何错误或任何东西,在那之后什么都没有 运行。我将读取和解码文件的代码移动到主线程的视图中,然后将提取的数据传递给新线程,然后一切正常。
我有一个 Django 应用程序,在管理员中有一个视图,允许员工用户上传一个 csv,然后将其传递给一个脚本,该脚本根据数据构建和更新数据库中的项目。视图 运行 在新线程中发送脚本,然后 returns 一条“上传开始”成功消息。
apps/products/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'))
apps/products/scripts/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 打印语句执行,但之后响应开始,其他打印语句 none 运行。过了一会儿,我查询了 EntryLog 模型,但没有进行任何更改。
从我读到的内容来看,我应该能够像在本地一样在 Heroku 上使用线程,但它似乎在主线程中执行脚本,然后在响应开始。
原来 Heroku 实际上打开了一个新线程就好了。当我调用 print(threading.currentThread())
时它显示 Thread-1 是一个转移注意力的问题。在我的开发环境 (Windows) 中,生成的线程总是打印 Thread-[number greater than 1],但是在 Heroku 环境中,我确定执行完成的简单线程的进一步测试总是打印 Thread-1。库在 Windows 和 Linux 上的功能可能有所不同? (这是我第一次使用线程库,如有遗漏,请见谅。)
实际问题似乎出在我读取 csv 文件的位置。后来有很多打印语句,我将其缩小到一切都停止的确切行 运行。我尝试了一个简单的测试,只是在一个新线程中读取一个 txt 文件,得到了相同的结果。没有抛出任何错误或任何东西,在那之后什么都没有 运行。我将读取和解码文件的代码移动到主线程的视图中,然后将提取的数据传递给新线程,然后一切正常。