在这种情况下如何关闭 MATLAB 会话?
How to close MATLAB session in this case?
我正在 运行 MATLAB 使用 Python 的 subprocess
像这样。 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
,主要的事情都在那里完成。
问题是,当 运行 宁 mainscript.m
时出现一些错误,
process
似乎被卡住了。并且 MATLAB 进程不会正常退出。
似乎 MATLAB 会话仍然是 运行ning 没有退出,因此 main.py
仍然是 运行ning 没有退出,这似乎被卡住了。但实际上 main.py
需要退出或发出一些警报。
所以我的问题是,在 /usr/local/MATLAB/R2017b/bin/matlab -r "run('mainscript.m');exit;
中出现错误时,有什么方法可以退出 MATLAB 会话吗?
期待您的建议。谢谢。
更新:
在阅读了友好的评论和回答后,我提供了更多细节以澄清这个问题。
main.py
是:
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()
run.sh
是:
/usr/local/MATLAB/R2017b/bin/matlab -r "run('matlabscript.m');exit;"
matlabscript.m
是(xxxx
不是有效的 function/script,这会导致错误。):
xxxx;
当运行宁python main.py
时,ps -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
被卡住 并且不会正常退出。所以我kill 4901
,然后ps -u
,它显示:
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
的子进程仍然 运行ning 没有退出。
但是,以下是可以的。
main_with_try_catch.py
是:
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()
run_with_try_catch.sh
是:
/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
,没有剩余进程。
运行 线程中的 subprocess
,如果没有正常退出,则在给定的超时后终止它。在此处查找示例:
要关闭进程,您可以在子进程中使用普通的 kill
:
kill -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
编辑
看完评论。
您可以连续读取脚本的输出,如果发现有趣的字符串,例如'error' 消息,只需终止 运行 进程(包括所有子进程):
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)
不要在 MATLAB 启动时使用 -r
到 运行 脚本。请改用 -batch
选项。
-r
选项表示“启动 MATLAB 和 运行 这个脚本,完成后留在命令提示符下”。该脚本旨在初始化环境。这就是为什么你的脚本需要以 exit
结尾,如果你想 运行 它是非交互的,就不会出错。
-batch
选项表示“运行 这个脚本然后以 success/failure 状态退出 MATLAB”。它旨在以非交互方式执行用 MATLAB 语言编写的脚本。它不显示初始屏幕,也不加载 GUI,而是通过 stdout 和 stderr 产生输出。参见 the docs。此选项从 R2019a 开始存在。
我正在 运行 MATLAB 使用 Python 的 subprocess
像这样。 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
,主要的事情都在那里完成。
问题是,当 运行 宁 mainscript.m
时出现一些错误,
process
似乎被卡住了。并且 MATLAB 进程不会正常退出。
似乎 MATLAB 会话仍然是 运行ning 没有退出,因此 main.py
仍然是 运行ning 没有退出,这似乎被卡住了。但实际上 main.py
需要退出或发出一些警报。
所以我的问题是,在 /usr/local/MATLAB/R2017b/bin/matlab -r "run('mainscript.m');exit;
中出现错误时,有什么方法可以退出 MATLAB 会话吗?
期待您的建议。谢谢。
更新:
在阅读了友好的评论和回答后,我提供了更多细节以澄清这个问题。
main.py
是:
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()
run.sh
是:
/usr/local/MATLAB/R2017b/bin/matlab -r "run('matlabscript.m');exit;"
matlabscript.m
是(xxxx
不是有效的 function/script,这会导致错误。):
xxxx;
当运行宁python main.py
时,ps -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
被卡住 并且不会正常退出。所以我kill 4901
,然后ps -u
,它显示:
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
的子进程仍然 运行ning 没有退出。
但是,以下是可以的。
main_with_try_catch.py
是:
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()
run_with_try_catch.sh
是:
/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
,没有剩余进程。
运行 线程中的 subprocess
,如果没有正常退出,则在给定的超时后终止它。在此处查找示例:
要关闭进程,您可以在子进程中使用普通的 kill
:
kill -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
编辑 看完评论。 您可以连续读取脚本的输出,如果发现有趣的字符串,例如'error' 消息,只需终止 运行 进程(包括所有子进程):
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)
不要在 MATLAB 启动时使用 -r
到 运行 脚本。请改用 -batch
选项。
-r
选项表示“启动 MATLAB 和 运行 这个脚本,完成后留在命令提示符下”。该脚本旨在初始化环境。这就是为什么你的脚本需要以 exit
结尾,如果你想 运行 它是非交互的,就不会出错。
-batch
选项表示“运行 这个脚本然后以 success/failure 状态退出 MATLAB”。它旨在以非交互方式执行用 MATLAB 语言编写的脚本。它不显示初始屏幕,也不加载 GUI,而是通过 stdout 和 stderr 产生输出。参见 the docs。此选项从 R2019a 开始存在。