python代码小知识之尽量不使用os.system()

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 
        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代码的安全性将会提高

生活很好,有你更好~~~

你可能感兴趣的:(python代码小知识之尽量不使用os.system())