2016-11-27 6 views
0

Я хотел бы флягу приложение, чтобы сообщить, сколько процессора и памяти, что в настоящее время используется в процентах:psutil всегда возвращает 0,0

import psutil 
from flask import Flask, request, jsonify 

app = Flask(__name__) 

@app.route("/test", methods=["GET"]) 
def healthz(): 
    return jsonify(msg="OK"), 200 

@app.route("/stats", methods=["GET"]) 
def stats(): 
    p = psutil.Process() 
    json_body = { 
     "cpu_percent": p.cpu_percent(interval=None), 
     "cpu_times": p.cpu_times(), 
     "mem_info": p.memory_info(), 
     "mem_percent": p.memory_percent() 
    } 
    return jsonify(json_body), 200 


def main(): 
    app.run(host="0.0.0.0", port=8000, debug=False) 

if __name__ == '__main__': 
    main() 

При отправке много запросов к/теста/статистика всегда будет возвращает 0,0 для cpu_percent:

$ while true; do curl http://127.0.0.1:8000/test &>/dev/null; done & 
$ curl http://127.0.0.1:8000/stats 
{ 
    "cpu_percent": 0.0, 
    "cpu_times": [ 
    4.97, 
    1.28, 
    0.0, 
    0.0 
    ], 
    "mem_info": [ 
    19652608, 
    243068928, 
    4292608, 
    4096, 
    0, 
    14675968, 
    0 
    ], 
    "mem_percent": 1.8873787935409003 
} 

Однако, если я вручную проверить с помощью IPython:

import psutil 
p = psutil.Process(10993) 
p.cpu_percent() 

Правильно возвращает значение больше 0,0.

+0

Это своего рода самореферентный; приложение будет потреблять дополнительные циклы и память, чтобы сообщать, сколько циклов и памяти они уже потребляют. Это может быть достигнуто с помощью других приложений и сервисов мониторинга процессов; почему вы хотите этого в своем приложении? – Makoto

ответ

1

Просто укажите «p = psutil.Process()» глобально (вне функции stat()). cpu_percent() отслеживает время процессора с момента последнего вызова, и именно так он может определить процент.

Первый вызов всегда будет равным 0,0, поскольку вычисление процента - это то, что требует сравнения двух значений с течением времени, и как таковое, должно пройти некоторое время.

1

Как указал Джампаоло, экземпляр Process должен находиться в глобальной области видимости, поскольку состояние треков отслеживает состояние, основанное на предыдущем вызове.

Следует помнить, что процентное соотношение между процессором может скачкообразно перескакивать с одного момента на другой, особенно когда период времени, который он рассчитывает, продолжает меняться, может быть довольно запутанным. Возможно, лучше использовать фоновый поток, который вычисляет среднее процентное соотношение CPU по заданным временным диапазонам.

Часть кода мне пришлось иметь под рукой, может представлять интерес:

from __future__ import print_function 

import os 
import time 
import atexit 

import threading 

try: 
    import Queue as queue 
except ImportError: 
    import queue 

import psutil 

_running = False 
_queue = queue.Queue() 
_lock = threading.Lock() 

_cpu_percentage = 1800 * [0.0] 
_processes = {} 

def _monitor(): 
    global _cpu_percentage 
    global _processes 

    while True: 
     marker = time.time() 

     total = 0.0 
     pids = psutil.pids() 

     processes = {} 

     for pid in pids: 
      process = _processes.get(pid) 
      if process is None: 
       process = psutil.Process(pid) 
      processes[pid] = process 
      total += process.cpu_percent() 

     _processes = processes 

     _cpu_percentage.insert(0, total) 

     _cpu_percentage = _cpu_percentage[:1800] 

     duration = max(0.0, 1.0 - (time.time() - marker)) 

     try: 
      return _queue.get(timeout=duration) 

     except queue.Empty: 
      pass 

_thread = threading.Thread(target=_monitor) 
_thread.setDaemon(True) 

def _exiting(): 
    try: 
     _queue.put(True) 
    except Exception: 
     pass 
    _thread.join() 

def track_changes(path): 
    if not path in _files: 
     _files.append(path) 

def start_monitor(): 
    global _running 
    _lock.acquire() 
    if not _running: 
     prefix = 'monitor (pid=%d):' % os.getpid() 
     print('%s Starting CPU monitor.' % prefix) 
     _running = True 
     _thread.start() 
     atexit.register(_exiting) 
    _lock.release() 

def cpu_averages(): 
    values = _cpu_percentage[:60] 

    averages = {} 

    def average(secs): 
     return min(100.0, sum(values[:secs])/secs) 

    averages['cpu.average.1s'] = average(1) 
    averages['cpu.average.5s'] = average(5) 
    averages['cpu.average.15s'] = average(15) 
    averages['cpu.average.30s'] = average(30) 
    averages['cpu.average.1m'] = average(60) 
    averages['cpu.average.5m'] = average(300) 
    averages['cpu.average.15m'] = average(900) 
    averages['cpu.average.30m'] = average(1800) 

    return averages 

я имел другие вещи в этом, который я удалил, так что надеюсь, что остается все еще находится в работоспособном состоянии.

Чтобы использовать его, добавьте в файл monitor.py, а затем импортируйте модуль в свою основную часть и запустите цикл мониторинга.

import monitor 
monitor.start_monitor() 

Тогда на каждом запросе вызова:

monitor.cpu_averages() 

и экстракт значение за период времени вы думаете, имеет смысл.

Смежные вопросы