hello,大家好,分享一个python代码小知识,如果我们使用的是linux环境,在使用python代码调用linux命令的时候,通常的做法就是os.system(),当然,一般情况下没什么问题,但是有些特殊情况,os.system()会导致一些不可预知的错误,如下:
1、os.system 本身不会在shell代码报错时停止运行
import os
os.system("echo start run error..")
os.system("ls xxx")
os.system("echo error can not stop me!")
运行上述脚本
$ python os_system_example.py
start run error..
ls: cannot access xxx: No such file or directory
error can not stop me!
可以看到error后不会终止
2、使用断言来控制os.system异常时无法查看异常的信息
由于os.system会返回一个推出状态码为0时代表程序正常推出,其他时候则为异常,因此可以使用断言来控制异常。使用断言来控制os.system的异常虽然比没有强,但是查看异常原因时却犯了难
import os
assert not os.system("echo start run error..")
assert not os.system("ls xxx")
assert not os.system("echo error can not stop me!")
运行脚本,在命令行中运行上述脚本,可以看到此时虽然会中断,但是没有报错信息。
$ python os_system_example.py
start run error..
ls: cannot access xxx: No such file or directory
Traceback (most recent call last):
File "os_system_example.py", line 4, in <module>
assert not os.system("ls xxx")
AssertionError
如何安全的调用linux命令呢?
这里介绍一些subprocess 模块,安全很多。
import subprocess as sp
cp = sp.run(cmd,shell=True,capture_output=True,encoding="utf-8")
这个方法可以代替os.system(),而且更加安全。
sp.run('ls .',shell=True,capture_output=True,encoding="utf-8")
返回
CompletedProcess(args='ls .', returncode=0, stdout='cluster_spatial.png\ndpt_pseudotime_cluster2.csv\nfigures\nspatial_trajectory_cluster_4.png\nspatial_trajectory_cluster_local_4.png\nspatial_trajectory_con_cluster.png\nspatial_trajectory_con_cluster_tree.png\nspatial_trajectory.h5ad\nspatial_trajectory.loom\nspatial_trajectory.png\ntest.sh\ntest.sh.e6508263\ntest.sh.o6508263\n', stderr='')
如果说命令错误呢?比如我们创建一个多级目录,但不使用参数
sp.run('mkdir /TJPROJ6/SC/personal_dir/zhaoyunfei/stlearn/test_stlearn_trajectory/zhaoyunfei/zz',shell=True,capture_output=True,encoding="utf-8")
###会看到报错,returncode=1,此时python会停止运行
CompletedProcess(args='mkdir /TJPROJ6/SC/personal_dir/zhaoyunfei/stlearn/test_stlearn_trajectory/zhaoyunfei/zz', returncode=1, stdout='', stderr='mkdir: cannot create directory ‘/TJPROJ6/SC/personal_dir/zhaoyunfei/stlearn/test_stlearn_trajectory/zhaoyunfei/zz’: No such file or directory\n')
###同样的条件使用os.system()
os.system('mkdir /TJPROJ6/SC/personal_dir/zhaoyunfei/stlearn/test_stlearn_trajectory/zhaoyunfei/zz')
mkdir: cannot create directory ‘/TJPROJ6/SC/personal_dir/zhaoyunfei/stlearn/test_stlearn_trajectory/zhaoyunfei/zz’: No such file or directory
####但python会往下运行
看到了吧, 上述就是用法的区别
这个命令的返回值returncode很重要,0表示正常执行,1表示出现错误,用在python代码中很方便。
我们尽量封装一个函数
def run_cmd(cmd):
"""
run command by using subprocess,
raise exception when error has happened
return standard output and standard error
"""
cp = sp.run(cmd,shell=True,capture_output=True,encoding="utf-8")
if cp.returncode != 0:
error = f"""Something wrong has happened when running command [{cmd}]:
{cp.stderr}"""
raise Exception(error)
return cp.stdout,cp.stderr
这样的话,python代码的安全性将会提高
生活很好,有你更好~~~