简体   繁体   English

Django-如何正确地向服务器发送请求并要求运行Matlab程序?

[英]Django - How to properly send a request to server and ask to run a matlab program?

I have a django web project on a server. 我在服务器上有一个django Web项目。 I want it to run a matlab code to produce some text file(which will be used later). 我希望它运行matlab代码以生成一些文本文件(稍后将使用)。 Here is my code: 这是我的代码:

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)

I ues a post request to run the octave code with subprocess call. 我发出一个后继请求,以通过子进程调用来运行八度代码。 However the matlab code take awhile to be finished and always make the client timeout which is not acceptable. 但是,matlab代码需要一段时间才能完成,并且总是使客户端超时是不可接受的。 My question is how to solve this kind of problem in another way. 我的问题是如何以另一种方式解决这种问题。 A post request seems not a good solution. 发布请求似乎不是一个好的解决方案。

You could make it async. 您可以使其异步。

And for async i mean that in the post request you will generate a uuid which identifies the operation. 对于异步,我的意思是在发布请求中,您将生成一个用于标识操作的uuid。 You will launch the operation inside the post request using a different thread/process. 您将使用其他线程/进程在发布请求内启动操作。

To check if the operation is done, you will have to setup a status view where given the operation id will return his status. 要检查操作是否完成,您将必须设置状态视图,在该视图中,给定的操作ID将返回其状态。

Adding just a code snippet as a proof of concept. 仅添加代码段作为概念证明。 I did not test it! 我没有测试!

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):
    .....
    .....

This would be an asyncronous operation. 这将是一个异步操作。 This is not built in to django by default, but there are several ways to make it possible. 默认情况下,它不是django内置的,但是有几种方法可以实现。

The most common choice is probably to use Celery. 最常见的选择可能是使用芹菜。 This is a distributed task queue that can be combined with django. 这是可以与Django结合使用的分布式任务队列。 It also requires that you install a message broker such as RabbitMQ. 它还要求您安装消息代理,例如RabbitMQ。

http://www.celeryproject.org/ http://www.celeryproject.org/

A newer alternative is django channels, which is part of the django project, but not a default part of django (at least not yet). 较新的替代方法是django频道,它是django项目的一部分,但不是django的默认部分(至少现在还没有)。

https://github.com/django/channels https://github.com/django/channels

See this question for more comparison of the two projects. 有关两个项目的更多比较,请参见此问题。 How Django channels are different than celery? Django频道与celery有何不同?

Both of these libraries are quite complex. 这两个库都很复杂。 If you are looking for more lightweight alternatives, see this question: 如果您正在寻找更轻巧的替代品,请参见以下问题:

Simple approach to launching background task in Django 在Django中启动后台任务的简单方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM