zoukankan      html  css  js  c++  java
  • Linux errno 与 Python

    以下均为Linux环境测试。

    起因:

    开发的一个程序,经常会由于内存不足而被kill掉,使用的是os.system函数执行的,返回值总是35072,当时没多想。后来由于一些原因,要模拟OOM 被kill的状态,于是调用 sys.exit(35072) 突然发现,返回值不对。。。 于是有了下面的。

     

    python中执行系统命令的方式一般来说有两种,os和subprocess(推荐)。

    简单用法如下:

    import os
    os.system("ls")
    # or
    import subprocess
    subprocess.call(["ls"])

     

    本文重点在于此两种方式的返回值差异问题。

    一、os.system

    此函数返回值即为 os.wait 函数返回值中的 exit status,查看官方文档对 os.wait 的解释:

    Wait for completion of a child process, and return a tuple containing its pid and exit status indication: a 16-bit number, whose low byte is the signal number that killed the process, and whose high byte is the exit status (if the signal number is zero); the high bit of the low byte is set if a core file was produced

    os.wait 返回一个元组,包含进程id和进程退出状态码。

    敲重点:

    进程退出码由两部分组成,分别是进程被kill的信号值和进程的退出码。

    这两个数字合并为一个16位的数字,前8位是退出码,后8位是kill信号。

    10进制计算方式:

    进程退出码 = 进程退出码 * 2 ** 8 + kill信号值

    测试:

    python中可以调用sys.exit或者os._exit来模拟各种退出码

    import os
    
    cmd = "python -c 'import sys;sys.exit(1)'"
    r = os.system(cmd)
    print(r)  # r = 256

    由于没有被kill,故kill信号值为0,所以 r = 1 * 2 ** 8 + 0 = 256

    当进程被kill时,则没有退出码,故 r = kill信号值

    tips:

    使用 os.WEXITSTATUS 可将 os.system 返回值还原为退出码

    二、subprocess.call

    此函数返回的是subprocess.Popen对象的returncode属性,这个没找到文档,直接看源码吧。

    def _handle_exitstatus(
        self,
        sts,
        _WIFSIGNALED=os.WIFSIGNALED,
        _WTERMSIG=os.WTERMSIG,
        _WIFEXITED=os.WIFEXITED,
        _WEXITSTATUS=os.WEXITSTATUS,
        _WIFSTOPPED=os.WIFSTOPPED,
        _WSTOPSIG=os.WSTOPSIG,
    ):
        """All callers to this function MUST hold self._waitpid_lock."""
        # This method is called (indirectly) by __del__, so it cannot
        # refer to anything outside of its local scope.
        if _WIFSIGNALED(sts):
            self.returncode = -_WTERMSIG(sts)
        elif _WIFEXITED(sts):
            self.returncode = _WEXITSTATUS(sts)
        elif _WIFSTOPPED(sts):
            self.returncode = -_WSTOPSIG(sts)
        else:
            # Should never happen
            raise SubprocessError("Unknown child exit status!")

    在源码中可发现,它对不同类型的退出码(或者叫退出码不太合适。。)做了判断,如果是被kill或被停止,则返回一个负值,如果是正常退出码,则原样返回。

    测试:

    import subprocess
    
    r = subprocess.call(["python", "-c", "import sys;sys.exit(1)"])
    print(r)  # r=1

    在没有被kill时,r = 退出码 = 1

    当被kill时,懒得写代码了,返回值是 -9、-15等

    参见:Linux 信号signal处理机制

     

    ps:

    Linux errno 的详细说明可参见:

    Linux errno详解

    补充一个:

    errno: 137 OOM killer 

     

    参考文献:

    C语言 unsigned与signed区别

    https://docs.python.org/3.7/library/subprocess.html#subprocess.Popen.wait

    https://docs.python.org/3.7/library/os.html#os.system

    https://shapeshed.com/unix-exit-codes/

  • 相关阅读:
    我的SICP习题解答-chapter 1
    redis主从复制实验,使用ruby
    python连接redis
    ruby连接redis
    python中的classmethod和staticmethod有什么不同[转载]
    安装配置rails环境
    试用memcached高可用repcached
    试用memcached
    Python一个很好玩的特性decorator
    mybatis随笔四之MapperProxy
  • 原文地址:https://www.cnblogs.com/dyfblog/p/10887943.html
Copyright © 2011-2022 走看看