Python'da bir başka programın(exe vs) çalışma süresini ölçme

Python’da çalışan işlemlerin çalışma süresini veren bir script yazmaya çalışıyorum. Bu Python’da mümkün mü bilmiyorum fakat Powershell ile yapılabileceğini buldum. Bunu subprocess kullanarak 2 satır kodla halledebildim ama çıktı berbat oluyor. Bu Powershell komutu ile tek bir işlemi nasıl alabilirim ve bu çıktıyı nasıl daha düzenli bir hale getirebilirim?

Kod:

import subprocess
print(subprocess.check_output("powershell Get-Process opera | select starttime"))

Çıktı:

b'\r\nStartTime  \r\n---------  \r\n12.12.2018 21:04:05                                                                                                    \r\n12.12.2018 21:04:05 \r\n12.12.2018 21:04:03                                                                                                    \r\n12.12.2018 21:04:03  \r\n12.12.2018 21:04:04                                                                                                    \r\n12.12.2018 21:04:04     \r\n12.12.2018 21:22:13                                                                                                    \r\n12.12.2018 21:04:04   \r\n12.12.2018 21:04:04                                                                                                    \r\n12.12.2018 21:04:04      \r\n12.12.2018 21:04:04  \r\n12.12.2018 21:04:06                                                                                                    \r\n12.12.2018 21:04:04\r\n\r\n\r\n'

timeit modülü sanıyorum bu işe yarıyor.

1 Beğeni

Ben Python işlemlerinin sürdüğü zamanı değil, diğer işlemlerin çalışma süresini istiyorum.

Biraz açabilir misiniz?

1 Beğeni

Herhangi çalışan bir programın çalışma süresini istiyorum.

Yazdığınız programın başlangıçtan itibaren ne kadar süre çalıştığı yani.
Time modülüne bakın.

import time
baslangic =  time.time()
#..... işlemlerin
saniye = time.time() - baslangic

saniye değişkenini yine time modülü ile biçimlendirip dakika, saat vb. zaman biçimlerine çevirebilirsiniz. Kolay gelsin.

1 Beğeni

Yazdığım program değil, diğer programlar. Örnek verecek olursam notepad ya da svchost.

Başlığı düzenledim, biraz daha net oldu sanki

Bir başka programın çalışması süresini elde etmek için aşağıdaki sayfada anlatılanları uygulayabilirsiniz.

Bu işlem zarfında geçen süreyi de yukarıda bahsedilen time.time() metodu ile elde edebilirsiniz. Mesela şöyle bir örnek yapalım

#coding:utf-8

import time,subprocess,sys

def getProgramRunTime(program_komut):

    process = subprocess.Popen(
        program_komut, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )
    
    basla = time.time()
    
    while True:
        out = process.stdout.read(1)
        if out == '' and process.poll() != None:
            break
        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()

    son = time.time()-basla

    print("Çalışma zamanı: {}".format(son))

getProgramRunTime("ping -t google.com -n 3")

Ping işlemi bittiğinde kaç saniye geçtiğini ekrana yazacaktır. Hatta notepad programını çalıştırın ve birkaç saniye sonra kapatın. Sonuçları görün :slight_smile:

2 Beğeni

Maalesef kodunuzda sıkıntı var. Kod not defterini açsa da zamanı göstermiyor hata veriyor.
Py3.7 kullanıyorum.

Hata:

Traceback (most recent call last):
  File "C:\Users\Wyren\Desktop\deneme.py", line 48, in <module>
    getProgramRunTime("notepad")
  File "C:\Users\Wyren\Desktop\deneme.py", line 41, in getProgramRunTime
    sys.stdout.write(out)
TypeError: must be str, not bytes

Python3.4 için gayet düzgün çalışıyor. Yine de 3.7 için şöyle bir düzeltme yapabilirsiniz.

#coding:utf-8

import time,subprocess

def getProgramRunTime(program_komut):

    process = subprocess.Popen(
        program_komut, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )
    
    basla = time.time()

    print("Program çalışıyor...")
    while True:
        if process.poll() != None:
            break

    son = time.time()-basla

    print("Bitti. Geçen süre: {}".format(son))

getProgramRunTime("ping -t google.com -n 3")
1 Beğeni

Yardımınız için teşekkürler. Peki bunu otomatik olarak yapabilir miyiz? Mesela kullanıcı Chrome’u açtı ve uygulama otomatikmen süreyi saymaya başladı. Sonra kullanıcı Chrome’u kapadı ve uygulama süreyi bir yere kaydetti.

Rica ederim. Bundan sonrası windows api programlamaya giriyor. Fikir vermesi açısından size şunu söyleyebilirim. Python ile process izleyici yaparsanız, yeni başlayan her process’i takip etme şansınız olur. WMI bu konuda size yardımcı olabilir sanırım.

Her yeni process başladığında bu process’e dair bilgileri ekrana yazan bir winapi programı. Sorularınız olursa hep beraber cevaplamaya çalışırız.

İyi forumlar.

2 Beğeni

Şuan az çok bir şeyler yaptım. Hatta çalışma süresini verebilecek bir plan var aklımda ama nasıl yapabileceğimi bilmiyorum. Kısa bir deneme yanılmayla koddaki
process_watcher = c.Win32_Process.watch_for("creation") kısmını
process_watcher2 = c.Win32_Process.watch_for("deletion") yapabileceğimizi öğrendim. Bu da bu kodun uygulamaların kapanışını izlediğini gösteriyor. print(process_watcher) kodunu biraz bilgi edinebilmek için kullandım ve "deletion"ın ne zaman olduğunu tıpkı "creation"daki gibi CreationDate ile tespit edebildiğimizi keşfettim. Çalışma süresini bulmak için yaptığım şey şuydu:

new_process = process_watcher()
closed_process = process_watcher2()
# diğer kodlar
create_date = new_process.CreationDate
close_date = closed_process.CreationDate
print(create_date-close_date)

Ama başarısız oluyordu. Anladığım kadarıyla uygulama kapanınca create_date değişkeninin içeriği sıfırlanıyor ve çıkarma işlemi başarısız oluyordu. Fakat print(create_date, close_date) yazınca düzgünce zamanları bastırıyor. Sizce bunun nedenleri ne olabilir?

Böyle bir şey olmaması gerek. Şunların çıktısı nedir:

print(type(create_date))
print(type(close_date))
1 Beğeni

<class 'str'> çıktısını veriyor. (str)-(str) işlemi gerçekleşmez diye biliyorum.
En sondaki

except:
    pass

kısmını düzenleyip hatayı bastıracak hale getirdim.
Sonra create_date ile close_date değişkenlerini int haline çevirmeye çalıştım. Hata verdi.
Hata:

ValueError: invalid literal for int() with base 10: '20181215112229.560957+180'

Sonra float haline çevirmeyi denedim yine hata verdi.
Hata:

ValueError: could not convert string to float: '20181215112438.994027+180'

Bu arada fark ettiğim bir şey oldu. CreationDate tüm tarihi veriyor. Bu sıkıntı çıkarabilir mi?

Şöyle bir durum var. Sizin CreationDate diye aldığınız zaman bizim işimize yaramaz. Bunun yerine iki olayı da ayrı ayrı dinlemeniz gerekir. Yani process başladığında başlama zamanını bir sözlüğe kaydedin, sonra da sonlanma bilgisi gelince de sözlükten başlama tarihini alarak çıkarma yapın. İki olayı da aynı anda dinlemek için Thread kullanabilirsiniz. Taslak şu şekilde olabilir

sözlük = {}

def baslama():
    # process başlangıçlarını dinleyen kısım
    # burada, her process başlangıç zamanını sözlüğe process adıyla kaydedebilirsiniz
    # yeni process başladığında
    sözlük[process_adi] = simdiki_zaman

def sonlanma():
    # sonlanan process ismini sözlükten veriyle beraber çekin ve şimdiki zamandan çıkarın
    sonuc = simdiki_zaman-sözlük[process_adi]

Bu arada, bu konuyla ilgili daha fazla bilgi almak isterseniz şu kaynaklara bakabilirsiniz


http://timgolden.me.uk/python/wmi/tutorial.html
https://docs.microsoft.com/en-us/windows/desktop/wmisdk/wmi-classes
https://docs.microsoft.com/tr-tr/windows/desktop/CIMWin32Prov/cim-service

Güncelleme: Process adı yerine ID kullanılırsa daha hatasız bir program olur. Çünkü aynı program iki kez açılınca karışıklık olacaktır.

2 Beğeni

Anlattığım algoritmaya göre programı yazdım. Ortaya şöyle bir sonuç çıktı.

# -*- coding: cp1254 -*-
import win32con
import win32api
import win32security
import wmi,time,threading
import pythoncom

sozluk = {}

class Process(object):
    # Process'leri daha kolay kontrol etmek için bir sınıf oluşturduk

    def __init__(self,process_id,process_path,start_time):
        self.process_id = process_id
        self.process_path = process_path
        self.start_time = start_time

def onCreate():
    # burası process oluşturulmasını dinleme
    print("Dinleniyor...")
    pythoncom.CoInitialize() # Thread içinde kullanılması önerilmiş. Bu yüzden kullandık
    c = wmi.WMI()
    process_watcher = c.Win32_Process.watch_for("creation")
    
    while True:
        try:
            new_process = process_watcher()
            executable  = new_process.ExecutablePath
            pid         = new_process.ProcessId

            sozluk[pid] = Process(pid,executable,time.time())
            print("Yeni bir process başladı: {}".format(pid))

        except:
            pass

    
def onDestroy():
    # burası process sonlanmasını dinleme
    
    pythoncom.CoInitialize()
    c = wmi.WMI()
    process_watcher = c.Win32_Process.watch_for("deletion")
    
    while True:
        try:
            new_process = process_watcher()
            pid         = new_process.ProcessId

            process = sozluk.get(pid,None)

            if(process != None):
                sonuc = time.time()-process.start_time
                print("[{}] {} programı {} saniye boyunca açık kaldı".format(pid,process.process_path,sonuc))
                sozluk[pid] = None

        except:
            pass

    

th1 = threading.Thread(target = onCreate)
th2 = threading.Thread(target = onDestroy)
th1.daemon = True
th2.daemon = True
th1.start()
th2.start()

input("Programı sonlandırmak için Enter'a basın\n")
pythoncom.CoUninitialize()

Bazı programları açıp kapattım

Yeni bir process başladı: 5948
[5948] C:\Windows\system32\notepad.exe programı 5.886718034744263 saniye boyunca açık kaldı
Yeni bir process başladı: 3852
Yeni bir process başladı: 4724
[3852] C:\Windows\system32\dxdiag.exe programı 24.152343034744263 saniye boyunca açık kaldı
[4724] C:\Windows\system32\calc.exe programı 3.955077886581421 saniye boyunca açık kaldı
1 Beğeni

Çok teşekkürler. Bu arada en sondaki
input("Programı sonlandırmak için Enter'a basın\n") biraz işi bozuyordu. Enter’a bastıktan sonra işlemlerin başlayıp sonlandığını gösteriyordu. Yani o kısım silinse çok daha iyi olabilir.

Rica ederim.

Enter’a bastıktan sonra işlemlerin başlayıp sonlandığını gösteriyordu.

Şu kısmı biraz daha açar mısınız? Tam olarak anlamadım kusura bakmayın.

1 Beğeni

Uygulama ben Enter’a basana kadar

Yeni bir process başladı: 5948
[5948] C:\Windows\system32\notepad.exe programı 5.886718034744263 saniye boyunca açık kaldı
Yeni bir process başladı: 3852
Yeni bir process başladı: 4724
[3852] C:\Windows\system32\dxdiag.exe programı 24.152343034744263 saniye boyunca açık kaldı
[4724] C:\Windows\system32\calc.exe programı 3.955077886581421 saniye boyunca açık kaldı

yazılarını göstermiyordu. Enter’a bastıktan sonra göstermeye başlıyordu.