» »

[Python3] Izvajanje ukazov po določenem času

[Python3] Izvajanje ukazov po določenem času

filips ::

V Pythonu 3 sem napisal program, ki preverja če je od zadnjič, ko se se ukazizagnali minilo več kot 30 sekund in izvede te ukaze. Istočasno preverja še za druge ukaze, ki se izvajajo na 10 sekund, poleg tega pa mora biti izpolnjen še nek pogoj.
Koda programa je:
from datetime import datetime

zadnjicIzvedeno1 = datetime(1, 1, 1)
zadnjicIzvedeno2 = datetime(1, 1, 1)

while True:
    utcnow = datetime.utcnow()
    if (utcnow - zadnjicIzvedeno1).total_seconds() >= 30:
        izvedeUkaze1()
        zadnjicIzvedeno1 = utcnow
    if (utcnow - zadnjicIzvedeno2).total_seconds() >= 10 and nekPogoj:
        izvedeUkaze2()
        zadnjicIzvedeno2 = utcnow

Program deluje, vendar je obremenitev procesorja visoka (poganjam na Raspberry Pi) in zato se tudi segreva. Zanima me, kako bi lahko program napisal tako, da obremenitev procesorja nebi bila tako visoka. Poskusil sem tudi s time.sleep, vendar to ni mogoče, ker imam dve vrsti ukazov, ki se morata izvesti ob različnih časih. Prosim za rešitev, ki bi bila tudi čimbolj natančna (da bi se ukazi zagnali na točno 30 in 10 sekund in ne pol sekunde kasneje).

noraguta ::

Sleep dej u zanko
Pust' ot pobyedy k pobyedye vyedyot!

filips ::

Za koliko časa? Imam dve vrsti ukazov, ki se morata izvesti ob različnih časih.

avian2 ::

Poglej si ta del standardne knjižnice:

https://docs.python.org/3/library/sched...

noraguta ::

Ja nekaj normalnega sekundo recimo. Važn je da una zanka ne nabija kot nora.
Pust' ot pobyedy k pobyedye vyedyot!

joze67 ::

Daš sleep za 9,5 s, greš v zanko do 10, izvedeš izvedeukaze2().
Ponoviš 2x
tretjič izvedeš še izvedeUkaze1()

Če sta operaciji dolgotrajni, pač ustrezno zmanjšaš čas spanja.

filips ::

Hvala vsem za pomoč. Zdaj deluje normalno.

ragezor ::

izracunaj si cas do naslednjega ukaza in das sleep za ta cas

noraguta ::

Saj ni kaj računat. Če sta izvedeUkaze1 in 2 časovno potratna jih v najbolšem primeru daš v vzporedno procesiranje. Če so v igri še kaki locki se pa stvar precej drugače zastavi. Tukaj je prvi problem, da zanka laufa ves čas procesorski cajt pa nuca na full za primerjavo dve časov.
Pust' ot pobyedy k pobyedye vyedyot!

filips ::

Imam še en majhen problem. Pri prejšnjem načinu je bil zamik le nekaj milisekund, zdaj sem pa uporabil sched in je zamik "kar" pol sekunde (najprej se zažene ob 0:0.0, potem ob 0:30.5, 1:1.0) in zato se po nekaj minutah zamik poveča na nekaj sekund.

noraguta ::

Pri prešnem načinu se je stvar zagnala takoj gledalo se je pa skos. Če imaš sedaj delay eno sekundo. Pade zadeva ravno v tiste pol sekunde. Enkrat več drugič manj.
Pojd na desetinko.
Pust' ot pobyedy k pobyedye vyedyot!

Isotropic ::

kako se naredi v pythonu, da lavfa en proces v ozadju, da lahko vmes še vedno izvajam user input?
rad bi indeksiral en dir (nad 1000 subfolderjev), če je kaj novega in parsal en xls za isto nalogo. oboje skupaj traja par sekund.

a so to slučajno asinhrone operacije (async)?

noraguta ::

Odvisno od nadaljnih zahtev. Ni to python. So osnove procesiranja. Python je samo realizacija čakanja. Rešitev je vedno mnogo. Idealke redke.
Pust' ot pobyedy k pobyedye vyedyot!

HotBurek ::

#!/usr/bin/python3.4

# import
import os;
import time;
import datetime;
import subprocess;

def ukaz1():
    print("Ukaz 1 | " + str(datetime.datetime.now()));
    # new process
    try:
        DEVNULL = open(os.devnull, 'w');
        # proc1 = subprocess.Popen(["python3.4", "/var/python/ukaz1.py", "id=1"], shell=False, stdout=DEVNULL);
    except Exception as err:
        print(err);

def ukaz2():
    print("Ukaz 2 | " + str(datetime.datetime.now()));
    # new process
    try:
        DEVNULL = open(os.devnull, 'w');
        # proc2 = subprocess.Popen(["python3.4", "/var/python/ukaz2.py", "id=2"], shell=False, stdout=DEVNULL);
    except Exception as err:
        print(err);

# main
while(True):
    dt = datetime.datetime.now().second;
    # DEBUG
    print(dt);
    if dt in [0, 10, 20, 30, 40, 50]:
        ukaz1();
        if dt in [0, 30]:
            ukaz2();
        # DEBUG
        print("Sleeping 8 seconds...");
        time.sleep(8);
    time.sleep(0.4);
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

HotBurek ::

Evo, sprememba na koncu, da je odstopanje od intervala v rangu do +0.05 sekunde. CPU pa zaradi tega pretirano ne trpi.

# main
while(True):
    dt = datetime.datetime.now().second;
    # DEBUG
    print(dt);
    if dt in [0, 10, 20, 30, 40, 50]:
        print("Ukaz 1 | " + str(datetime.datetime.now()));
        # ukaz1();
        if dt in [0, 30]:
            print("Ukaz 2 | " + str(datetime.datetime.now()));
            # ukaz2();
        # DEBUG
        print("Sleeping 8 seconds...");
        time.sleep(8);
    else:
        if str(dt).endswith("9"):
            time.sleep(0.05);
        else:
            time.sleep(0.4);
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

Isotropic ::

burek a lahko še zame poveš
a so to async metode ali multiprocessing? načeloma bi v main threadu delal user input ipd.

ragezor ::

uporabi multithreading/multiprocessing

noraguta ::

ragezor je izjavil:

uporabi multithreading/multiprocessing

Kr škoda te je za vsak dan.

Isotropic je izjavil:

burek a lahko še zame poveš
a so to async metode ali multiprocessing? načeloma bi v main threadu delal user input ipd.

Ni problem, stane vračaš gor. Daš izvajanje na druho nit al pa proces. ... Pol je pa. Tam problem. Kdo dostopa... Daržje kot če samo zanki uzdo natakneš.
Pust' ot pobyedy k pobyedye vyedyot!

Zgodovina sprememb…

  • spremenilo: noraguta ()

HotBurek ::

kako se naredi v pythonu, da lavfa en proces v ozadju, da lahko vmes še vedno izvajam user input?

To lahko narediš kot je zgoraj napisano, da odpreš nov process.

import os;
import subprocess;
DEVNULL = open(os.devnull, 'w');
proc = subprocess.Popen(["python3.4", "/var/python/scann.py", "someparameterifyouneedone=abc"], shell=False, stdout=DEVNULL);

FYI v scann.py se parameter (ali več njih), prebere takole:

import sys:
for i in range(len(sys.argv)):
arg = sys.argv[i];
print(arg);


Če tako odpreš process, ki skenira folderje, le-ta ne bo blokiral main processa. V scan procesu potem narediš while loop. Zraven pa definiraš nek file "/var/python/scan.config" za dve stvari;
Prvo, da scan vpisuje, kar je interesantno za main (npr kdaj je bil nazadnje izveden scan, število skeniranih folderejev, % done, itn.) Te podatke lahko prebere main skripta, ter prikaže status scan skripte.
Drugo, da lahko preko flag-a (npr. enable=true/false) v config fajlu ustaviš scan (ali ga nastavljaš po svoje, time delay itn...)
root@debian:/# iptraf-ng
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window

jype ::

Spregledali ste najbolj pythonistično rešitev, ki jo je predlagal avian2.

Ktj ::

Kot kaže je dejansko predlagana rešitev od avian2 najboljša - bi bilo potrebno testirati kako natančno se izvede exec funkcije. V kolikor je pa potrebno vpeljati še dodatne pogoje je pa verjetno potrebna "custom rešitev". Vse rešitve v navedeni temi predvidevajo, da imamo samo dva klica za narediti, kaj pa če je potrebno narediti več klicev? Glede na OP zahteve podajam rešitev, ki bi jo sam uporabil. Natančnost klicev funkcij je ~5 ms in CPU obremenitev je okoli 0.5%. Lahko, da se bo to na Rasbary Pi drugače obnašalo temu primerno je potrebno spremeniti IDILE_TIME.

Glede na uporabljene funkcije je najboljša možna natančnost ~1.5 ms, če je pa potrebna natančnost boljša kot pa 1.5ms, je pa potrebna druga rešitev (glej odgovor od noragute).
Testirano na Windows 10, python 3.6

import time

class ExecHelper:
    def __init__(self, execFunction, conditionFunction, sleepTime):
        self.execFunction = execFunction
        self.conditionFunction = conditionFunction
        self.sleepTime = sleepTime
        self.lastRun = time.time()

    def run(self): 
        if (time.time() - self.lastRun) > self.sleepTime:
            self._displayStats();
            self.lastRun += self.sleepTime
            if self.checkCondition():
                self.execFunction()
                
    def _displayStats(self):
        deltaTime = time.time() - self.lastRun
        print("Actual time elapsed for execution: %.2f (ms) vs sleepTime: %.1f (ms)" \
              % (deltaTime * 1000.0, self.sleepTime*1000.0))

    def checkCondition(self):
        result = True
        if self.conditionFunction != None:            
            result = self.conditionFunction()
        return result

class Scheduler:
    IDILE_TIME = 5 # idile time in ms
    
    def __init__(self):
        self.functions = []
        self._actualSleepTime = []
    
    def addExec(self, functionName, functionCondition, sleepTime):
        self.functions.append(ExecHelper(functionName, functionCondition, sleepTime))
          
    def run(self):
        while(True):
            
            for item in self.functions:
                item.run()
            time.sleep(self.IDILE_TIME / 1000)

def functionOne():
    print("Running function one")
    
def functionTwo():
    print("Running function two")

def functionTwoCondition():
    return True

sch = Scheduler()
sch.addExec(functionOne, None, 1)
sch.addExec(functionTwo, functionTwoCondition, 2)

if __name__ == "__main__":
    sch.run()

noraguta ::

Nenkomplicirat. Evente se uporablja pri bolj neterminističnih zadevah in kjer je kuonzadev za katere jentreba vodit zadeve. Pri relativno oreproatih zadevah.. Sleepaš
Tud napake je treba polovit.
Pust' ot pobyedy k pobyedye vyedyot!


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Skripta za Bolho.

Oddelek: Programiranje
304430 (1842) planina91
»

Postavitev mySQL

Oddelek: Programiranje
92227 (1805) M01O
»

Fake traffic generator

Oddelek: Omrežja in internet
192246 (1442) HotBurek
»

Pošljite nam vašo najboljšo kodo

Oddelek: Programiranje
122175 (1420) AndrejO
»

[python] project euler problem

Oddelek: Programiranje
151279 (831) Spura

Več podobnih tem