검색하기귀찮아서만든블로그

[Python] 프로세스 시스템 자원 측정 본문

개발

[Python] 프로세스 시스템 자원 측정

hellworld 2022. 4. 16. 10:58

사용자가 지정한 프로세스의 자원을 측정하여 CSV 파일로 생성하는 코드입니다.

프로세스가 생성한 자식 프로세스까지 측정합니다. (1차 자식 프로세스까지 측정)

결과 파일명 : YYYYmmDD_HHmmSS_resource_parent.csv, YYYYmmDD_HHmmSS_resource_child.csv

 

psutil 패키지 설치 : pip install psutil

실행 파라미터 : -w <대상 PID> 

메모리는 '작업 집합' 필드를 기록합니다.

# -*- coding: utf-8 -*-
# psutil 패키지 설치 : pip install psutil 
import psutil
import sys, getopt
import signal
from time import time, sleep, strftime, localtime
import csv
import threading

g_isThreadRun = True

# 종료 이벤트 발생 시 스레드 종료 플래그를 설정하고 종료한다.
def signal_handler(signal, frame):
    global g_isThreadRun
    g_isThreadRun = False
    sleep(3)
    sys.exit(0)

# 시스템 리소스 체크 스레드 함수
def threadWriteResource(processObj, FileName):
    global g_isThreadRun
    try:
        # CSV 파일을 오픈한다. (with 구문이 빠져 나가면 파일이 갱신)
        with open(FileName , 'w', newline='') as f:

            # CSV Write 객체를 생성한다.
            w = csv.DictWriter(f, fieldnames=['TIME', 'CPU (%)', 'Memory (MByte)'])

            # CSV 헤더 정보를 기록한다.
            w.writeheader()

            # CPU Core 수를 구한다.
            cpu_cnt = psutil.cpu_count()

            # CSV 를 기록하기 위한 딕셔너리를 생성한다.
            dictRow = dict()
            while g_isThreadRun:

                curTime = strftime('%H:%M:%S', localtime(time()))
                cpuUse = round(processObj.cpu_percent(interval=1.0) / cpu_cnt, 2)
                memUse = processObj.memory_info()._asdict().get('wset', 0)
                memUseKByte = round(memUse / 1024, 3)
                memUseMByte = round(memUseKByte / 1024, 3)

                # 딕셔너리 구조로 정보를 기록한다.
                dictRow['TIME'] = curTime
                dictRow['CPU (%)'] = cpuUse
                dictRow['Memory (MByte)'] = memUseMByte

                # CSV 에 row 를 기록한다.
                w.writerow(dictRow)

    except Exception as e:
        print('[{0}] Exception: {1}'.format(processObj.pid, e))
            
# 프로그램 메인문
if __name__ == '__main__':
    
    TargetPid = 0
    # 도움말
    def help():
        print('            \n\t-t <target_pid>\t\t\t(default: {0})'.format(TargetPid))

    # 실행 파라미터 설정
    try:
        opts, etc_args = getopt.getopt(sys.argv[1:], 'ht:', ['help', 'target_pid='])
    except getopt.GetoptError as e:
        print(e)
        help()
        sys.exit(2)

    # 실행 파라미터 파싱
    for opt, arg in opts:
        if opt in ('-h', '--help'):
            help()
            sys.exit(2)
        elif opt in ('-t', '--target_pid'):
            TargetPid = int(arg)
    
    # CSV 파일 시간 (파일명)
    csvFileTime = strftime('%Y%m%d_%H%M%S', localtime(time()))
    signal.signal(signal.SIGINT, signal_handler)
    
    # 대상 프로세스 PID 검사
    if 0 == TargetPid:
        print('Target PID is 0.')
        sys.exit(1)

    

    # 대상 프로세스 정보 객체 생성
    procParent = psutil.Process(TargetPid)

    # 시스템 리소스 체크 스레드 생성 (Parent 프로세스 전용)
    threadResource = threading.Thread(target=threadWriteResource, args=(procParent, '{0}_{1}_resource_parent.csv'.format(csvFileTime, TargetPid)))
    threadResource.daemon = True
    threadResource.start()

    # 관리 리스트에 추가
    threadList = list()
    threadList.append(threadResource)

    # 대상 프로세스의 자식 프로세스들의 시스템 리소스 체크 스레드 생성
    for procChild in procParent.children():
        threadResource = threading.Thread(target=threadWriteResource, args=(procChild, '{0}_{1}_resource_child.csv'.format(csvFileTime, procChild.pid)))
        threadResource.daemon = True
        threadResource.start()

        threadList.append(threadResource)

    print('Total {0} process.'.format(len(threadList)))

    # 스레드 종료 대기        
    try:
        isAliveProcess = True
        while isAliveProcess:
            isAliveProcess = False
            for threadResource in threadList:
                if not threadResource.is_alive():
                    continue
                isAliveProcess = True
            sleep(1)
    except Exception as e:
        print('Exception: {1}'.format(e))
        g_isThreadRun=False
        sleep(3)
        sys.exit(2)