python os模块system_python 中 os.system 的本质 | 编程知识2

python 中 os 模块用得比较多,但 os.system 实际上是怎么调用 shell 命令的呢?简单来探寻一下。

1、系统环境

macos 10.15.6 x86_64

python 3.8.5

为什么要强调系统环境,因为 python 在不同系统版本上实现可能会有差异,待会讲解就能发现了。

2、os 模块

通过 help(os) 可以找到源文件查看,

下面截取相关代码来看(直接用注释解释了):

# 返回一个包含内建模块名字的元组,包含所有已经编译到Python解释器的模块名字

_names = sys.builtin_module_names

# __all__ 只影响到了 from import * 这种导入方式

def _get_exports_list(module):

try:

return list(module.__all__)

except AttributeError:

return [n for n in dir(module) if n[0] != '_']

# 判断当前操作系统类型

# posix代表类Unix系统,nt表示Windows系统

# 我们的 macOS 就是类Unix系统,只截取这部分代码

if 'posix' in _names:

name = 'posix' # 表示操作系统类型

linesep = '\n' # 定义了当前平台使用的行终止符

# os模块其实就是对posix或nt模块的二次封装,这样的好处就是实现了对不同平台的兼容

from posix import *

try:

from posix import _exit

__all__.append('_exit')

except ImportError:

pass

import posixpath as path # 我们常用的os.path实际上是ntpath或者posixpath模块

try:

from posix import _have_functions

except ImportError:

pass

import posix

__all__.extend(_get_exports_list(posix))

del posix

现在我们知道了在 macos 平台上,os 模块实际上是对 posix 模块的封装。

2.1、subprocess 模块

顺道再看看 subprocess 调用的实现:

if shell: #制作 shell 的参数

args = ["/bin/sh", "-c"] + args

if executable:

args[0] = executable

if executable is None:

executable = args[0]

# ··· ···

self.pid = os.fork() #创建子进程

# ··· ···

os.execvp(executable, args) #执行 shell 命令

3、posix 模块

posix 即 Portable Operating System Interface(可移植操作系统接口),是类 Unix 系统的兼容标准。

同样通过 help(posix) 看下是否有源文件,

可以看到 posix 是 built-in module,代表是直接编译好放在 python 这个可执行文件里的。

可以在 module 的 config.c 中找到相关的转接代码。

extern void initposix(void);

struct _inittab _PyImport_Inittab[] = {

{"posix", initposix},

// ...

3.1、对 built-in 模块的继续查找

实际上对于 built-in 模块还能继续查找,首先要弄清楚当前 python 的虚拟机是用什么实现的:

可以看到 macos 系统 python 虚拟机是 CPython 实现的。

CPython 是开源的,那么我们可以从 cpython 中找到相关的源码:

static PyMethodDef posix_methods[] = {

... ...

#ifdef HAVE_SYSTEM {"system", posix_system, METH_VARARGS, posix_system__doc__},

#endif... ...

};

#ifdef HAVE_SYSTEMPyDoc_STRVAR(posix_system__doc__,

"system(command) -> exit_status\n\n\Execute the command (a string) in a subshell.");

// 在Python中操作的任何元素都是一個由C語言實現的PyObject對象static PyObject *

posix_system(PyObject *self, PyObject *args)

{

char *command;

long sts;

if (!PyArg_ParseTuple(args, "s:system", &command))

return NULL;

Py_BEGIN_ALLOW_THREADS // 允许其他线程获取 GIL 锁来跑 sts = system(command); // system call(或其他不会操作Python Data的调用) Py_END_ALLOW_THREADS // 重新获取 GIL 锁 return PyInt_FromLong(sts);

}

#endif

可以看到 posix.system 最终会调用 C 的 system 函数。

C 的 system 函数就不需要再深入进去了,在 C/C++ 网站有很多介绍。

4、结论

macos 系统下:

os.system -> posix.system -> C 的 system 函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值