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 函數
總結
以上是生活随笔為你收集整理的python os模块system_python 中 os.system 的本质 | 编程知识2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kindle刷多看系统_疑问解答 | k
- 下一篇: python定义变量并赋值_Python