Forum » Programiranje » [Python3] Izvajanje ukazov po določenem času
[Python3] Izvajanje ukazov po določenem času
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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:
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).
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).
![](https://static.slo-tech.com/stili/bel_non_grata.png)
noraguta ::
Ja nekaj normalnega sekundo recimo. Važn je da una zanka ne nabija kot nora.
Pust' ot pobyedy k pobyedye vyedyot!
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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.
Ponoviš 2x
tretjič izvedeš še izvedeUkaze1()
Če sta operaciji dolgotrajni, pač ustrezno zmanjšaš čas spanja.
![](https://static.slo-tech.com/stili/bel_non_grata.png)
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!
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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.
![](https://static.slo-tech.com/stili/bel_non_grata.png)
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.
Pojd na desetinko.
Pust' ot pobyedy k pobyedye vyedyot!
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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)?
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)?
![](https://static.slo-tech.com/stili/bel_non_grata.png)
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!
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
![](https://static.slo-tech.com/stili/avatar_gray.gif)
Isotropic ::
burek a lahko še zame poveš
a so to async metode ali multiprocessing? načeloma bi v main threadu delal user input ipd.
a so to async metode ali multiprocessing? načeloma bi v main threadu delal user input ipd.
![](https://static.slo-tech.com/stili/bel_non_grata.png)
noraguta ::
uporabi multithreading/multiprocessing
Kr škoda te je za vsak dan.
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 ()
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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...)
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
fatal: This program requires a screen size of at least 80 columns by 24 lines
Please resize your window
![](https://static.slo-tech.com/stili/avatar_gray.gif)
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
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()
![](https://static.slo-tech.com/stili/bel_non_grata.png)
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.
Tud napake je treba polovit.
Pust' ot pobyedy k pobyedye vyedyot!
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Skripta za Bolho.Oddelek: Programiranje | 4350 (1762) | planina91 |
» | Postavitev mySQLOddelek: Programiranje | 2174 (1752) | M01O |
» | Fake traffic generatorOddelek: Omrežja in internet | 2182 (1378) | HotBurek |
» | Pošljite nam vašo najboljšo kodoOddelek: Programiranje | 2136 (1381) | AndrejO |
» | [python] project euler problemOddelek: Programiranje | 1250 (802) | Spura |