簡體   English   中英

Django-如何正確地向服務器發送請求並要求運行Matlab程序?

[英]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。

http://www.celeryproject.org/

較新的替代方法是django頻道,它是django項目的一部分,但不是django的默認部分(至少現在還沒有)。

https://github.com/django/channels

有關兩個項目的更多比較,請參見此問題。 Django頻道與celery有何不同?

這兩個庫都很復雜。 如果您正在尋找更輕巧的替代品,請參見以下問題:

在Django中啟動后台任務的簡單方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM