[英]Django - How to properly send a request to server and ask to run a matlab program?
我在服務器上有一個django Web項目。 我希望它運行matlab代碼以生成一些文本文件(稍后將使用)。 這是我的代碼:
if(request.method == "POST"):
run_octave(Dataset,is_multiclass,require_mapper,mapper,require_aspect_ratio,aspect_ratio)
return redirect('meta2db.views.meta2db')
def run_octave(dataset,is_multiclass,require_mapper,mapper,require_aspect_ratio,aspect_ratio):
origWD = os.getcwd()
args = ["octave", "dbEval.m",dataset,is_multiclass,require_mapper,\
mapper,require_aspect_ratio,aspect_ratio]
os.chdir(os.path.join(os.path.abspath(sys.path[0]), "../scripts/"))
#subprocess call here
process = subprocess.Popen(args, stdout=subprocess.PIPE)
for line in process.stdout:
time.sleep(0.5)
Group("eval_status").send({"text": line.decode('utf-8')},immediately=True)
if process.poll() is None:
process.kill()
else:
print(process.communicate())
os.chdir(origWD)
我發出一個后繼請求,以通過子進程調用來運行八度代碼。 但是,matlab代碼需要一段時間才能完成,並且總是使客戶端超時是不可接受的。 我的問題是如何以另一種方式解決這種問題。 發布請求似乎不是一個好的解決方案。
您可以使其異步。
對於異步,我的意思是在發布請求中,您將生成一個用於標識操作的uuid。 您將使用其他線程/進程在發布請求內啟動操作。
要檢查操作是否完成,您將必須設置狀態視圖,在該視圖中,給定的操作ID將返回其狀態。
僅添加代碼段作為概念證明。 我沒有測試!
from concurrent.futures import ThreadPoolExecutor
import uuid
class Operation(object):
operations = {}
def __init__(self, *task):
self.id = str(uuid.uuid4())
self.task = task
self.done = False
self._thread = None
self._executor = ThreadPoolExecutor()
self.__class__.operations[self.id] = self
def run(self):
self._thread = self.executor.submit(*self.task)
self._thread.add_done_callback(self._callback)
return self.id
def _callback(self):
self.done = True
@classmethod
def is_operation_done(cls, id):
try:
return cls.operations[id].done
except IndexError:
raise Exception("Operation not found") # FIXME Custom exception here!!
if(request.method == "POST"):
operatiorn = Operation(run_octave,
Dataset,
is_multiclass,
require_mapper,
mapper,
require_aspect_ratio,
aspect_ratio)
id = operatiorn.run()
return id # jsonize it if you wanna pass it to the frontend
def is_operatiorn_done(request, operation_id):
# This is implementing a polling but would be bettere to have a socket!
return Operation.is_operation_done(operation_id)
def run_octave(dataset,is_multiclass,require_mapper,mapper,require_aspect_ratio,aspect_ratio):
.....
.....
這將是一個異步操作。 默認情況下,它不是django內置的,但是有幾種方法可以實現。
最常見的選擇可能是使用芹菜。 這是可以與Django結合使用的分布式任務隊列。 它還要求您安裝消息代理,例如RabbitMQ。
較新的替代方法是django頻道,它是django項目的一部分,但不是django的默認部分(至少現在還沒有)。
https://github.com/django/channels
有關兩個項目的更多比較,請參見此問題。 Django頻道與celery有何不同?
這兩個庫都很復雜。 如果您正在尋找更輕巧的替代品,請參見以下問題:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.