在这种情况下,如何关闭MATLAB会话?

2024-06-16 13:59:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用Python的subprocess运行MATLAB,如下所示。该main.py如下所示:

process = subprocess.Popen("bash run.sh", stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
stdout = process.communicate()[0]

run.sh是这样的:

export PATH=...
/usr/local/MATLAB/R2017b/bin/matlab -r "run('mainscript.m');exit;"

在{}中,主要的事情是在那里完成的

问题是,当运行mainscript.m时出现一些错误, {}似乎被卡住了。并且MATLAB过程不会正常退出。 MATLAB会话似乎仍在运行而没有退出,因此main.py仍在运行而没有退出,这似乎被卡住了。但实际上main.py需要退出或发出一些警报

所以我的问题是,当/usr/local/MATLAB/R2017b/bin/matlab -r "run('mainscript.m');exit;中发生错误时,有没有办法退出MATLAB会话

期待着您的建议。谢谢

更新:

在阅读了善意的评论和回答之后,我提供了更多的细节来澄清这个问题

{}是:

import subprocess
import time
from threading import Thread


def main(param1):
    process = subprocess.Popen('bash run.sh', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
    start = time.time()
    stdout = process.communicate()[0]
    elapsed = time.time() - start
    print('log: {}, {}, {}'.format(param1, stdout, elapsed))


if __name__=='__main__':
    _param = {"param1":"param1"}
    thread = Thread(target=main, kwargs=_param)
    thread.start()

{}是:

/usr/local/MATLAB/R2017b/bin/matlab -r "run('matlabscript.m');exit;"

matlabscript.m是(xxxx不是有效的函数/脚本,这会导致错误。):

xxxx;

运行python main.pyps -u的输出为:

ubuntu    4901  0.0  0.0 218624  5392 pts/4    Sl+  08:10   0:00 python main.py
ubuntu    4903  0.0  0.0 113280  1192 pts/4    S+   08:10   0:00 bash run.sh
ubuntu    4904  9.0  3.1 5702484 512812 pts/4  Sl+  08:10   0:06 /usr/local/MATLAB/R2017b/bin/glnxa64/MATLAB -r run('matlabscript.m');exit; -prefersoftwareopengl
ubuntu    5025  0.0  0.0 115544  2004 pts/3    Ss   08:11   0:00 -bash
ubuntu    5044  0.0  0.0 155436  1852 pts/3    R+   08:11   0:00 ps -u

而且python main.py被卡在那里,不能正常退出。所以我{},然后{},它显示:

ubuntu    4903  0.0  0.0 113280  1192 pts/4    S    08:10   0:00 bash run.sh
ubuntu    4904  4.7  3.1 5702484 512812 pts/4  Sl   08:10   0:06 /usr/local/MATLAB/R2017b/bin/glnxa64/MATLAB -r run('matlabscript.m');exit; -prefersoftwareopengl
ubuntu    5025  0.0  0.0 115544  2052 pts/3    Ss   08:11   0:00 -bash
ubuntu    5047  0.0  0.0 155436  1852 pts/3    R+   08:12   0:00 ps -u

这意味着MATLAB的子进程仍在运行,没有退出

但是,以下是可以的。 {}是:

import subprocess
import time
from threading import Thread


def main(param1):
    process = subprocess.Popen('bash run_with_try_catch.sh', stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
    start = time.time()
    stdout = process.communicate()[0]
    elapsed = time.time() - start
    print('log: {}, {}, {}'.format(param1, stdout, elapsed))


if __name__=='__main__':
    _param = {"param1":"param1"}
    thread = Thread(target=main, kwargs=_param)
    thread.start()

{}是:

/usr/local/MATLAB/R2017b/bin/matlab -r "try,run('matlabscript.m'),catch,fprintf('error occured'),end;exit;"

然后,运行python main_with_try_catch.py,它显示:

[ubuntu@localhost ~]$ python main_with_try_catch.py
log: param1, MATLAB is selecting SOFTWARE OPENGL rendering.

                                                                              < M A T L A B (R) >
                                                                    Copyright 1984-2017 The MathWorks, Inc.
                                                                     R2017b (9.3.0.713579) 64-bit (glnxa64)
                                                                               September 14, 2017


To get started, type one of these: helpwin, helpdesk, or demo.
For product information, visit www.mathworks.com.

error occured, 7.47159695625
[ubuntu@localhost ~]$

这意味着MATLAB将正常退出。并检查ps -u,没有剩余进程


Tags: runpybashtimemainubuntuusrsh
2条回答

不要在MATLAB的启动中使用-r来运行脚本。改用-batch选项

-r选项显示“启动MATLAB并运行此脚本,完成后停留在命令提示符处”。该脚本用于初始化环境。这就是为什么您的脚本需要以exit结束,并且如果您希望以非交互方式运行它,则不能出错

-batch选项显示“运行此脚本,然后以成功/失败状态退出MATLAB”。它旨在以非交互方式执行用MATLAB语言编写的脚本。它不显示启动屏幕,也不加载GUI,通过stdout和stderr生成输出。见the docs。此选项自R2019a起存在

在线程中运行subprocess,如果未正常退出,则在给定超时后终止它。请在此处查找示例: https://stackoverflow.com/a/4825933/4620675

要关闭进程,您可以在子进程中使用普通的killkill -TERM $(pgrep -f matlab)

或使用方法:

    import os
    import signal
    def find_process_and_close(process_name):
        output = subprocess.getoutput("ps -A -o pid= -o cmd=")
        for line in output.splitlines():
            if process_name in line:
                pid = int(line.split()[0])
                os.kill(pid, signal.SIGTERM)
                print("Terminate process {}".format(line))
                return True
        return False

使用psutil包的另一种方法:

    import psutil
    def find_process_and_close_with_psutil(process_name):
        for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
            if proc.info['cmdline'] and process_name in proc.info['cmdline']:
                print("Terminate process {}".format(proc.info))
                proc.kill()
                return True
        return False

编辑 看完评论。 您可以连续读取脚本的输出,如果发现有趣的字符串,例如“错误”消息,只需终止正在运行的进程(所有子进程):

    proc = subprocess.Popen(["bash run.sh"],
                            preexec_fn=os.setsid, # to kill all spawned processes
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
    pid_to_terminate = None
    try:
        for stdout_line in iter(proc.stdout.readline, ''):
            line = stdout_line.decode().strip()
            print(line)
            #look for 'error' in the output
            if "error" in line:
                print("ERROR found in script output")
                pid_to_terminate = proc.pid
                break
    finally:
        proc.stdout.close()
    
    if pid_to_terminate:
        # kill with all spawned processes
        os.killpg(os.getpgid(pid_to_terminate), signal.SIGTERM)

相关问题 更多 >