最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python?異常、捕獲和退出,進(jìn)程調(diào)用輸出示例解析

 更新時(shí)間:2026年02月07日 09:47:09   作者:aworkholic  
文章詳細(xì)介紹了Python中的異常處理機(jī)制,探討了進(jìn)程調(diào)用,使用popen解析標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出,并獲取進(jìn)程返回值的方法,文章簡(jiǎn)要介紹了使用psutil庫進(jìn)行進(jìn)程控制的方法,感興趣的朋友跟隨小編一起看看吧

第一部分,說明 try … except … finally 之間的邏輯,并且在 使用 exit函數(shù)的區(qū)別。

第二部分,進(jìn)程調(diào)用,使用popen 解析標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出,獲取進(jìn)程返回值的問題。

1、異常和捕獲

1.1、常規(guī)示例

# problematic_subprocess.py
import sys
import os
import time
def func():
    for i in range(3):
        print(f"Iteration {i}")
        # 正常輸出
        print("This is a normal stdout message.")
        print("Another stdout message.", file=sys.stdout)
        time.sleep(1)
        # 錯(cuò)誤輸出
        print("This is a stderr message.", file=sys.stderr)
        print("Another stderr message.", file=sys.stderr)
    return 0
if __name__ == "__main__":
    ret = 0 # 作為后面預(yù)留使用
    try:
        ret = func()
        print(f"{__file__}: Return code: {ret}")
    except Exception as e:
        print(f"{__file__}: Exception: {e}")
        ret = -1
    finally:
        print(f"{__file__}: Finally block executed.")
        print(f"{__file__}: Exiting with return code: {ret}")

這里使用try執(zhí)行func函數(shù), func函數(shù)中沒間隔1s秒使用標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤輸出打印,最后返回0。 若有異常則打印異常信息。最后執(zhí)行finally邏輯,不論是否有異常,這里都會(huì)執(zhí)行。

結(jié)果輸出

Iteration 0
This is a normal stdout message.
Another stdout message.
This is a stderr message.
Another stderr message.
Iteration 1
This is a normal stdout message.
Another stdout message.
This is a stderr message.
Another stderr message.
Iteration 2
This is a normal stdout message.
Another stdout message.
This is a stderr message.
Another stderr message.
c:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Return code: 0
c:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Finally block executed.
c:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Exiting with return code: 0

1.2、拋出異常

在前面例子上, 將 main 的返回語句修改

    # return 0
    raise Exception("An exception occurred.")

執(zhí)行結(jié)果,這里忽略func函數(shù)的輸出。 異常拋出被捕獲,之后,繼續(xù)執(zhí)行了finally部分。

c:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Exception: An exception occurred.
c:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Finally block executed.
c:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Exiting with return code: -1

1.3、進(jìn)程退出與異常

進(jìn)程退出,有 os._exit()sys.exit() (不建議在生產(chǎn)中使用 exit()函數(shù) )兩種,可以附帶返回值,作為整個(gè)進(jìn)程的返回值。

首先。雖然主要是說明異常,但為了說明后續(xù)問題,這里提供一個(gè)進(jìn)程調(diào)用方式,來判斷進(jìn)程退出的返回值。

1.3.1、進(jìn)程調(diào)用獲取程序的返回值

import subprocess
if __name__ == "__main__":
    process = subprocess.Popen(["python", "problematic_subprocess.py"])
    ret_code = process.wait()
    print("Return code: {}".format(ret_code))

使用 subprocess 啟動(dòng)一個(gè)進(jìn)程, 使用python 執(zhí)行腳本 problematic_subprocess.py,之后使用 wait() 等待結(jié)束獲取返回值。

# problematic_subprocess.py
print("hello world!")

運(yùn)行后,打印輸出信息, 獲取得到的返回值為 0 。 正常結(jié)束、且不執(zhí)行返回碼的進(jìn)程,返回值為 0。

hello world!
Return code: 0

1.3.2、sys.exit(status: int)

繼續(xù)修改前述測(cè)試代碼,調(diào)用 sys.exit 中斷 func 函數(shù)執(zhí)行

    # return 0
    # raise Exception("An exception occurred.")
    sys.exit(2)

運(yùn)行進(jìn)程測(cè)試腳本,func程序提前退出,但執(zhí)行了try…finally… 的部分,且進(jìn)程返回碼為指定值。

C:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Finally block executed.
C:\Users\admin\Desktop\process_popen\problematic_subprocess.py: Exiting with return code: 0
Return code: 2

1.3.3、os._exit(status: int)

繼續(xù)修改前述測(cè)試代碼,調(diào)用 os._exit 中斷 func 函數(shù)執(zhí)行

    # return 0
    # raise Exception("An exception occurred.")
    # sys.exit(2)
    os._exit(3)

執(zhí)行進(jìn)程測(cè)試腳本,func程序退出,沒有執(zhí)行了try…finally… 的部分,進(jìn)程返回碼為指定值

Return code: 3

1.3.4、os.abort()

abort比較特殊,主要是發(fā)送終止信號(hào),由于這里沒有編寫信號(hào)處理部分,不做討論。

繼續(xù)修改前述測(cè)試代碼,調(diào)用 os.abort() 中斷 func 函數(shù)執(zhí)行

    # return 0
    # raise Exception("An exception occurred.")
    # sys.exit(2)
    # os._exit(3)
    os.abort() 

執(zhí)行進(jìn)程測(cè)試腳本,func程序退出,沒有執(zhí)行了try…finally… 的部分,且返回指為一個(gè)很大的數(shù)值

Return code: 3221226505

1.4、sys.exit()、os._exit()與os.abort()對(duì)比表

特性sys.exit()os._exit()os.abort()
模塊來源sys 模塊os 模塊os 模塊
實(shí)現(xiàn)機(jī)制拋出 SystemExit 異常直接調(diào)用系統(tǒng) _exit() 函數(shù)發(fā)送 SIGABRT 信號(hào)
清理操作? 執(zhí)行(finally 塊、上下文管理器等)? 不執(zhí)行任何清理? 不執(zhí)行任何清理
可被捕獲? 可通過捕獲 SystemExit 異常? 無法捕獲? 無法捕獲
退出碼控制? 可指定(默認(rèn) 0)? 可指定? 固定(通常為 134)
核心轉(zhuǎn)儲(chǔ)? 不生成? 不生成? 可能生成(取決于系統(tǒng)配置)
適用場(chǎng)景正常程序退出、腳本終止子進(jìn)程退出、避免資源泄漏嚴(yán)重錯(cuò)誤、調(diào)試崩潰
跨平臺(tái)一致性? 高? 高?? 行為可能因平臺(tái)而異
Pythonic 程度? 官方推薦方式?? 特殊場(chǎng)景使用?? 調(diào)試/異常場(chǎng)景使用
對(duì)緩沖區(qū)影響? 正常刷新 stdout/stderr? 可能丟失未刷新的輸出? 可能丟失未刷新的輸出

使用建議

  • 日常開發(fā):優(yōu)先使用 sys.exit()
  • 多進(jìn)程編程:子進(jìn)程中使用 os._exit() 避免干擾父進(jìn)程
  • 調(diào)試/崩潰分析:使用 os.abort() 觸發(fā)核心轉(zhuǎn)儲(chǔ)進(jìn)行事后分析

2、進(jìn)程調(diào)用與輸出解析

2.1、進(jìn)程調(diào)用

注意,這里在使用popen打開進(jìn)程,使用了2個(gè)線程讀取標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤輸出, 將原進(jìn)程輸出分別重定向到對(duì)應(yīng)的日志文件中。日志的的寫入,使用了logging庫。最后等待進(jìn)程退出。

日志控制中,可以要求按照指定格式進(jìn)行正則化匹配,例如 進(jìn)度,程序運(yùn)行結(jié)果,程序異常的結(jié)果等。自行擴(kuò)展。

import subprocess
import threading
import logging
def setup_loggers(stdout_log_file="stdout.log", stderr_log_file="stderr.log"):
    """
    為 stdout 和 stderr 創(chuàng)建獨(dú)立的日志記錄器
    """
    # 配置日志格式
    log_format = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )
    # 設(shè)置 stdout 日志記錄器
    stdout_logger = logging.getLogger("STDOUT")
    stdout_logger.setLevel(logging.INFO)
    stdout_handler = logging.FileHandler(stdout_log_file, mode='w', encoding='utf-8')
    stdout_handler.setFormatter(log_format)
    stdout_logger.addHandler(stdout_handler)
    # 設(shè)置 stderr 日志記錄器
    stderr_logger = logging.getLogger("STDERR")
    stderr_logger.setLevel(logging.ERROR)
    stderr_handler = logging.FileHandler(stderr_log_file, mode='w', encoding='utf-8')
    stderr_handler.setFormatter(log_format)
    stderr_logger.addHandler(stderr_handler)
    # 防止日志傳播到根記錄器
    stdout_logger.propagate = False
    stderr_logger.propagate = False
    return stdout_logger, stderr_logger
def write_stream_to_logger(stream, logger, level=logging.INFO):
    """將流中的數(shù)據(jù)實(shí)時(shí)寫入日志記錄器"""
    print(f"write_stream_to_logger: {logger.name}")
    for line in stream:
        # 去除行尾的換行符
        log_message = line.rstrip('\n\r')
        logger.log(level, log_message)
def run_process_and_log_output(command, stdout_file="stdout.txt", stderr_file="stderr.txt"):
    """
    使用 Popen 執(zhí)行命令,并實(shí)時(shí)將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤寫入指定文件,
    無論進(jìn)程是否正常結(jié)束。
    """
    # 設(shè)置日志記錄器
    stdout_logger, stderr_logger = setup_loggers(stdout_file, stderr_file)
    try:
        print(f"Starting process: {command}")
        # 啟動(dòng)子進(jìn)程
        process = subprocess.Popen(
            command,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            # bufsize=1,
            universal_newlines=True,
            shell=isinstance(command, str)
        )
        # 輸出進(jìn)程相關(guān)信息
        print(f"Process started with PID: {process.pid}")
        # 創(chuàng)建線程來處理 stdout 和 stderr
        stdout_thread = threading.Thread(
            target=write_stream_to_logger, 
            args=(process.stdout, stdout_logger, logging.INFO)
        )
        stderr_thread = threading.Thread(
            target=write_stream_to_logger, 
            args=(process.stderr, stderr_logger, logging.ERROR)
        )
        # 啟動(dòng)線程
        stdout_thread.start()
        stderr_thread.start()
        # 等待進(jìn)程結(jié)束
        return_code = process.wait()
        # 等待線程完成
        stdout_thread.join()
        stderr_thread.join()
        print(f"Process finished with return code: {return_code}")
        return return_code
    except Exception as e:
        print(f"An error occurred: {e}")
        with open(stdout_file, 'w', encoding='utf-8') as f:
            f.write("")
        with open(stderr_file, 'w', encoding='utf-8') as f:
            f.write(f"An error occurred: {e}")
        return -2
        # raise
    finally:
        # 確保文件被關(guān)閉
        if process.stdout:
            process.stdout.close()
        if process.stderr:
            process.stderr.close()
# 示例用法
if __name__ == "__main__":
    problematic_cmd = ["python", "problematic_subprocess.py"]
    print("Running problematic subprocess...")
    ret_code = run_process_and_log_output(problematic_cmd, "stdout.txt", "stderr.txt")
    print(f"Problematic subprocess finished with return code: {ret_code}")		
    ```
以上代碼中,不論前述problematic_subprocess.py是如何執(zhí)行,return_code = process.wait() 都會(huì)成功,接收到進(jìn)程的返回值。
例如在 func 中 拋出異常, 進(jìn)程不顯式指定返回指,那么進(jìn)程默認(rèn)返回值為0。 實(shí)際輸出也符合預(yù)期
```py
Running problematic subprocess...
Starting process: ['python', 'problematic_subprocess.py']
Process started with PID: 24808
write_stream_to_logger: STDOUT
write_stream_to_logger: STDERR
Process finished with return code: 0
Problematic subprocess finished with return code: 0

其中2個(gè)文件內(nèi)容如下,也同樣滿足預(yù)期

2.2、進(jìn)程控制 psutil

進(jìn)程控制可以使用 psutil 庫

        # 等待1s,通知退出
        time.sleep(1)
        import psutil
        master_process = psutil.Process(process.pid)
        if master_process.is_running():
            print("Process is still running, sending SIGTERM...")
            master_process.terminate()
            time.sleep(1)
            if master_process.is_running():
                print("Process is still running, sending SIGKILL...")
                master_process.kill()
                time.sleep(1)
                if master_process.is_running():
                    print("Process is still running, giving up...")
                    return -1

到此這篇關(guān)于python 異常、捕獲和退出,進(jìn)程調(diào)用輸出示例解析的文章就介紹到這了,更多相關(guān)python 異常捕獲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python處理中文標(biāo)點(diǎn)符號(hào)大集合

    Python處理中文標(biāo)點(diǎn)符號(hào)大集合

    中文文本中可能出現(xiàn)的標(biāo)點(diǎn)符號(hào)來源比較復(fù)雜,通過匹配等手段對(duì)他們處理的時(shí)候需要格外小心,防止遺漏,下面小編給大家?guī)砹薖ython處理中文標(biāo)點(diǎn)符號(hào)大集合,感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-05-05
  • python文件處理--文件讀寫詳解

    python文件處理--文件讀寫詳解

    這篇文章主要介紹了Python 處理文件的幾種方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • django項(xiàng)目簡(jiǎn)單調(diào)取百度翻譯接口的方法

    django項(xiàng)目簡(jiǎn)單調(diào)取百度翻譯接口的方法

    這篇文章主要介紹了django項(xiàng)目簡(jiǎn)單調(diào)取百度翻譯接口的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-08-08
  • Python3 集合set入門基礎(chǔ)

    Python3 集合set入門基礎(chǔ)

    集合也也也也是python內(nèi)置的一種數(shù)據(jù)結(jié)構(gòu),它是一個(gè)無序且元素不重復(fù)的序列。這里有兩個(gè)關(guān)鍵詞一個(gè)是無序,這一點(diǎn)和字典是一樣的,另一個(gè)關(guān)鍵詞是元素不重復(fù),這一點(diǎn)和字典的key(鍵)是一樣的
    2020-02-02
  • 從入門到封裝通用詳解Python裝飾器實(shí)戰(zhàn)指南

    從入門到封裝通用詳解Python裝飾器實(shí)戰(zhàn)指南

    這篇文章主要介紹了為大家詳細(xì)介紹了Python中裝飾器使用的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2026-01-01
  • Python zip()函數(shù)的用法和技巧(解鎖并行迭代的魔力)

    Python zip()函數(shù)的用法和技巧(解鎖并行迭代的魔力)

    zip()函數(shù)是Python中一個(gè)簡(jiǎn)潔而強(qiáng)大的工具,它通過并行迭代多個(gè)序列,讓代碼更加優(yōu)雅和易讀,這篇文章給大家介紹Python zip()函數(shù)完全指南:解鎖并行迭代的魔力,感興趣的朋友跟隨小編一起看看吧
    2026-02-02
  • python 集合 并集、交集 Series list set 轉(zhuǎn)換的實(shí)例

    python 集合 并集、交集 Series list set 轉(zhuǎn)換的實(shí)例

    今天小編就為大家分享一篇python 集合 并集、交集 Series list set 轉(zhuǎn)換的實(shí)例。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • 如何在Python中安裝GDAL庫

    如何在Python中安裝GDAL庫

    這篇文章主要介紹了如何在Python中安裝GDAL庫,GDAL是一個(gè)在X/MIT許可協(xié)議下的開源柵格空間數(shù)據(jù)轉(zhuǎn)換庫,需要的朋友可以參考下
    2023-04-04
  • Python selenium使用autoIT上傳附件過程詳解

    Python selenium使用autoIT上傳附件過程詳解

    這篇文章主要介紹了Python selenium使用autoIT上傳附件過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • python使用Flask框架獲取用戶IP地址的方法

    python使用Flask框架獲取用戶IP地址的方法

    這篇文章主要介紹了python使用Flask框架獲取用戶IP地址的方法,實(shí)例分析了Python使用Flask框架remote_addr獲取IP的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-03-03

最新評(píng)論

金堂县| 高平市| 抚顺市| 静宁县| 芦溪县| 新龙县| 德江县| 察隅县| 泾川县| 永平县| 香格里拉县| 海伦市| 南和县| 景东| 靖远县| 土默特右旗| 资阳市| 内乡县| 乐昌市| 盘山县| 拉孜县| 永城市| 抚宁县| 麦盖提县| 江城| 兴宁市| 鄂尔多斯市| 黄大仙区| 柘荣县| 岐山县| 海林市| 安龙县| 霸州市| 淮阳县| 玉树县| 临高县| 英超| 大足县| 门头沟区| 惠来县| 山阴县|