歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Python os模塊進程函數

Python os模塊進程函數

日期:2017/3/1 9:08:52   编辑:Linux編程

Table of Contents

  • 1. 系統進程
  • 2. 舉例
    • 2.1. os.fork
    • 2.2. os.exec 和 os.system
    • 2.3. os.wait
  • 3. 總結

系統進程

今天在看《Beginning Linux Programming》中的進程相關部分,講到Linux幾個進程相關的系統函數: system, exec, fork, wait. Python的 os 模塊實現了對應的函數封裝了這些系統調用: os.system, os.exec, os.fork, os.wait.

1. os.system(command)
# 在一個程序內部啟動另一個程序,從而創建一個新進程
# os.system 在一個shell中執行command命令,這是一個對C函數system()的python實現,具有相同的限制條件。在Unix系統中,返回值是命令執行後的退出狀態值。由於POSIX沒有為C函數system()的返回值指定明確的含義,所以os.system()的返回值依# 賴具體的系統。在Windowns中,返回值由系統環境變量決定: COMSPEC, 此環境變量依據不同系統版本不同
# 因為os.system的局限性,官方文檔建議用 subprocess模塊的功能來代替此函數

2. os.exec系列
os.execl(path, arg0, arg1, ...)
os.execle(path, arg0, arg1, ..., env)
os.execlp(file, arg0, arg1, ...)
os.execlpe(file, arg0, arg1, ..., env)
os.execv(path, args)
os.execve(path, args, env)
os.execvp(file, args)
os.execvpe(file, args, env)
# 這些函數都執行一個新的程序,然後用新的程序替換當前子進程的進程空間,而該子進程從新程序的main函數開始執行。在Unix下,該新程序的進程id是原來被替換的子進程的進程id。原來的程序不再運行。在原來子進程中打開的所有描述符默認都是可用的,不會被關閉。
# execv*系列的函數表示其接受的參數是以一個list或者是一個tuple表示的參數表
# execl*系列的函數表示其接受的參數是一個個獨立的參數傳遞進去的。
# exec*p*系列函數表示在執行參數傳遞過去的命令時使用PATH環境變量來查找命令
# exec*e系列函數表示在執行命令的時候讀取該參數指定的環境變量作為默認的環境配置,最後的env參數必須是一個mapping對象,可以是一個dict類型的對象。

3. os.fork (只在Unix有效)
# 要想讓進程同時執行多個函數,可以使用線程或者從原程序中創建一個完全分離的進程。可以通過fork創建一個新進程。這個調用復制當前進程,在系統的進程表上創建一個新表項,新表項中的許多屬性與當前進程相同。但新進程有自己的數據空間、環境和文件描述符
# os.fork出一個子進程,在子進程中返回0,在父進程中返回子進程ID,如果發生錯誤,則拋出OSError異常
# 注意:在一些平台下如FreeBSD,Cygwin和OS/2 EMX系統中使用該函數會有問題。

4. os.wait (只在Unix有效)
# 當fork啟動一個子進程時,子進程有了自己的生命周期並獨立運行,有時候希望知道一個子進程何時結束,這時可以通過wait函數讓父進程等待子進程運行結束
# os.wait 等待任何一個子進程結束,返回一個tuple,包括子進程的進程ID和退出狀態信息:一個16位的數字,低8位是殺死該子進程的信號編號,而高8位是退出狀態(如果信號編號是0),其中低8位的最高位如果被置位,則表示產生了一個core文件。
# 相關的的有os.waitpid(pid, options)

舉例

os.fork

#!/usr/bin/python
#coding=utf-8
import os

def child():
    print('hello from child', os.getpid(), os.getppid())    #前者獲取進程id, 或者獲取父進程id
    os._exit(0)     # 退出進程, 通常只用在fork() 產生的子進程中

def parent():
    pid = os.fork()   # 返回的pid在父進程中為子進程PID,在資進程中為0, 所以下面根據pid判斷是哪個進程
    if pid == 0:
        child()
        print 'fork child process error!'    #如果打印該字符串,說明調用child()出錯
    else:
        print('hello from parent', os.getpid(), pid)

parent()

我電腦上運行結果如下:

-> python test.py

('hello from parent', 1952, 1953)
('hello from child', 1953, 1952)

os.exec 和 os.system

os.execlp的測試代碼如下:

#!/usr/bin/python
#coding=utf-8
import os

def main():
    print "Running ps with execlp"
    os.execlp("ps", 'ps', 'ax')
    print "Done."

main()

運行結果:

-> python test4.py
Running ps with execlp
  PID   TT  STAT      TIME COMMAND
    1   ??  Ss     0:12.43 /sbin/launchd
   42   ??  Ss     0:03.05 /usr/libexec/UserEventAgent (System)
   43   ??  Us     0:05.24 /usr/sbin/syslogd
...
  481 s000  S+     0:00.14 -zsh
 1803 s001  Ss+    0:00.49 /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versio
 1806 s002  Ss     0:00.10 /bin/zsh -i
 2070 s002  R+     0:00.02 ps ax

os.system的測試代碼如下:

#!/usr/bin/python
#coding=utf-8
import os

def main():
    print "Running ps with execlp"
    os.system("ps ax")
    print "Done."

main()

運行結果如下:

-> python test4.py
Running ps with execlp
  PID   TT  STAT      TIME COMMAND
    1   ??  Ss     0:12.71 /sbin/launchd
   42   ??  Ss     0:03.11 /usr/libexec/UserEventAgent (System)
...
  481 s000  S+     0:00.14 -zsh
 1803 s001  Ss+    0:00.50 /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versio
 1806 s002  Ss     0:00.10 /bin/zsh -i
 2113 s002  S+     0:00.02 /usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versio
 2114 s002  R+     0:00.00 ps ax
Done.

以上兩個例子對比可以看到 exec系列 的調用使得原進程接下的代碼都不會運行。

os.wait

#! /usr/bin/python
#coding=utf-8

import os
import sys

def child_process():
    '''child process'''
    print 'child process is running'
    sys.exit(0)                 # 常用的退出進程

def parent_process():
    '''parent process'''
    print 'parent process is running'
    print 'waiting for child process'
    exit_stat = os.wait()     # 返回值是一個pid 和退出狀態的元組
    print "waited child process's PID = %d" % (exit_stat[0])
    sys.exit(0)

def main():
    '''main function'''
    try:
        pid = os.fork()
        if pid > 0:
            '''parent process'''
            parent_process()
        else:
            child_process()
    except OSError, e:
        print os.strerror(e.errno)


main()

運行結果:

-> python test4.py
parent process is running
waiting for child process
child process is running
waited child process's PID = 2152

總結

本文簡單介紹了系統進程相關的 os.system, os.exec, os.fork, os.wait 系統調用。相關的其它調用如:
os.kill, os.ncie, os.popen, os.spawn系列 可以參照官方文檔。另外實際上python多進程編程更加推薦 multiprocessing 模塊提供的相關功能,將在以後的文章中探究。

Copyright © Linux教程網 All Rights Reserved