Ahoj mám problém a to tento :
# Vymyslel jsem tohle abych zabil funkci loop() - respektive vypocet v ni ktery bezi dele nez chci.
# Funguje to, ale...
import time
import threading
a=55654
def loop():
while(1):
print "a*a"
try:
print a*a # pokud tady bude a**a tak to vyresit neumim. Zakousne se a nehne!
time.sleep(0.50)
except:
print " uleva !"
break
t=threading.Timer(0.0, loop)
t.start()
time.sleep(5.50)
a="DIE!"
raw_input()
# Jak prerusit prave probihajici vypocet a**a ?? Pripadne jak jinak by se toto dalo resit ??
Děkuji
Fórum › Python
Zabiti vypočtu v pythonu.
Quiark napsal:
Tuším, že to bude výsledek global interpreter locku - když se počítá a*a, tak žádný jiný kód kvůli tomu neběží, takže ho ani nemůže zastavit. Pokud to tak je, tak s tím nic moc nenaděláš.
Nechci působit nějak hrubě, ale to je hloupost. GIL sice způsobuje, že v jednom okamžiku běží jen jedna část kódu, ale mezi těmito částmi přepíná. Jde o to, že zavoláním "a**a" se zavolá jakási funkce umocni() s parametry (a,a), které se v tomto případě předávají hodnotou, tudíž pozdější změna "a" nijak neovlivní to, co se dostalo do umocňovací funkce. Nejjednodušší je pravděpodobně rozebrat "a**a" na menší kroky, které nebudou zabírat tak velký časový úsek. Také by to chtělo trochu změnit způsob zabití vlákna. Sice je pravda, že Python je tolerantní jazyk a právě díky GIL se nemůže stát, že by se v tomto programu něco zkazilo, ale v jakémkoliv jiném jazyce by čtení z proměnné a zároveň probíhající zápis do ní vedlo k nedefinovanému chování. Pokud by tě zajímalo, jak bych tuto úlohu řešil já, posílám ti svůj kód.
import time
import threading
class locked_var:
def __init__(self,var):
self.lock=threading.Lock()
self.var=var
def set(self,var):
self.lock.acquire()
self.var=var
self.lock.release()
def get(self):
self.lock.acquire()
ret=self.var
self.lock.release()
return ret
class loop_thread(threading.Thread):
def __init__(self,condition,a):
threading.Thread.__init__(self)
self.condition=condition
self.a=a
self.res=0
def run(self):
n=1
res=self.a
while self.condition.get() and n<self.a:
# dokud to neni zpocitano nebo neni vlakno ukonceno
res*=self.a
n+=1
print "bylo zpocitano a**"+str(n)
self.res=res
self.condition.set(True) # oznam, ze byl vysledek ulozen
a=55654
cond=locked_var(True)
t=loop_thread(cond,a)
print "startuji vlakno s parametrem "+str(a)
t.start()
time.sleep(5.5)
print "posilam signal na zastaveni..."
cond.set(False)
while not cond.get(): time.sleep(0.1) # cekame, az se vlakno doopravdy zastavi
# a ulozi vysledek
# vysledek je nyni v t.res
print "\nted jdu vysledek vytisknout, ale protoze"
print "ho nejdrive musim prevest z cisla na retezec,"
print "muze to trvat i nekolik minut"
print t.res
print "\nhotovo"
raw_input()
Koumes21: Velice děkuji za Váš příspěvěk. Vaše řešení bude pro mne jistě velkou inspirací, ale pár dní ho budu chroustat, protože jsem naprostý začátečník. Ten kód je plný míst kterým nerozumím. Mohl bych Vás poprostit, aby jste ho opoznámkoval? Snad se pak v tom doberu nějakého řešení. V tomto stavu je pro mě nepoužitelný protože ono "a**a" se generuje náhodně. - Přesněji ten program generuje jakýkoliv náhodný polynom, který pak počítá a na místě "a**a" tedy může být klidně například. :
s=s*j(5142-(f(a**11407))**(-4429.86681**(-80393.862)))
# Dále je pak takových to řádků pod sebou v jednom výpočtu několik.
s=(s+-4*(2905.4*(a(m(p)))))
s=s...
(S tím že j,f je libovolná matematická funkce například sin... atd.) Proto mě zajímalo pouze jak co nejrychlejším způsobem zabít určytý výpočet přípedně funkci s tím, že není nutné nijak zachovat výsledek. Zajímalo by mě klidně jakkoliv násilné a hrubé přerušení výpočtu. Pokud nastane situace např. a**a a nebo jiná která by trvala příliš dlouho je vzorec nepoužitelný a není nutné se s ním dále zabývat.
Poslal bych sem celý program, ale věřím že by jste se v něm nechtěl vyznávat :o)) ... toto je poslední problém který v něm mám mám. Každopádně ještě jednou děkuji za Váš čas.
... případně ještě by mě tedy tajímalo jestli jde nastavit tedy thread tak, aby by spustil nějakou funkci, ale dal jí na dokončení jen určitý počet sekund. Například 5. Pokud by funkce nedošla do konce do pěti sekund, tak by byla prostě ukončena. Prostě opak
"t=threading.Timer(5.0, loop) "
Děkuji.
Operační systém většinou povoluje zabití vlákna, jenže problém je, že vlákno nedostane příležitost po sobě uklidit. Některé programovací jazyky dají programátorovi příležitost vlákno zabít, Python ovšem nikoliv, protože je jaksi zaměřen na začátečníky a nechce jim dávat do rukou zbraň hromadného ničení, kterou neumí ovládat. Nejlepší by bylo, kdybys měl možnost nějak výrazy zjednodušit, například vkládáním funkcí do pole a voláním jedné funkce po druhé.
funkce = [
lambda x: 2*x+1,
lambda x: x+5,
lambda x: x/2
]
n=1
for f in funkce:
n=f(n)
print n
Pokud ovšem jsou výrazy generovány náhodně, může být složité je takto zjednodušit.
P.S.: Dobře, možná existuje možnost jak zabít vlákno. Našel jsem ukázku kódu v Pythonu, který by toto měl dělat, viz. http://www.velocityreviews.com/forums/t330554-kill-a-thread-in-python.html, ale protože ho sám nehodlám použít, budeš muset zjistit detaily jeho použití sám. Znovu opakuji, že je možné, že nebude fungovat absolutně tak jak má a že bude dělat problémy - zaseknutí programu, nadměrné zaplňování paměti atd.
ještě ke komentářům k programu: třída locked_var je náhrada za tvou původní globální proměnnou a, ale je bezpečné volat funkce get() a set() ze dvou různých vláken současně, protože třída používá zámek, který před čtením nebo zápisem zamkne a potom zase odemkne. Nepamatuji si, jestli je v dokumentaci Pythonu něco o tom, že GIL tohle zajistí pro každou proměnnou, je to možné, ale i tak je lepší používat tento postup, i kdyby to mělo být jen kvůli tomu, že to tak je v jiných jazycích. Třída loop_thread je náhrada za tvoje loop(), dejme tomu, že je ekvivalentní, ale podle mě je rozumnější použít klasickou cestu, neboť Timer slouží ke spuštění funkce po nějakém čase, což není přesně to co chceme. loop_thread.__init__() si pouze uloží parametry, které jí předáme a zavolá __init__() funkci třídy threading.Thread, ze které je odvozená. Funkce run() je potom ta funkce, která bude zavolána v novém vlákně až zavolám start(), která je zděděna z threading.Thread.
Ještě si dovolím konstruktivní kritiku ke tvému programu: nepoužívej pouze "except:", vždy uveď kterého typu výjimky se to týká. Například v tvém případě by to bylo "except TypeError:". Je to proto, že i stisknutí Ctrl+C vyvolá výjimku a ty bys ji takhle odchytil, což není to co ty chceš a program by pak nešel tímto způsobem přerušit. I kdybys nevěděl, který typ chyby použít, uveď alespoň "except Exception:". Exception je třída odvozená od BaseException, ale KeyboardInterrupt je odvozen přímo od BaseException a ne od Exception, tudíž odchytávání Exception nezachytí KeyboardInterrupt. Asi jsem to napsal dost nepřehledně, takže doufám, že jsem tě tím ještě více nezmátl.
Ještě se omlouvám, teď jsem si přečetl, že ten kód v tom odkazu nebude v tvém případě fungovat, protože dokáže přerušit pouze operaci, která je zaseklá v kódu Pythonu, ale ne tu, která je zaseklá v nějakém kódu na nižší úrovni, což je právě tvůj případ. Ještě jednou se tedy omlouvám za falešnou naději.
Děkuji za vysvětlení prvního kódu.
koumes21 napsal:
Operační systém většinou povoluje zabití vlákna, jenže problém je, že vlákno nedostane příležitost po sobě uklidit. Některé programovací jazyky dají programátorovi příležitost vlákno zabít, Python ovšem nikoliv, protože je jaksi zaměřen na začátečníky a nechce jim dávat do rukou zbraň hromadného ničení, kterou neumí ovládat...
Nebylo by tedy nějak možné naimportovat do Pythonu nějakou knihovnu z jiného jazyka, která by toto umožnila? Nebo něco v tomto smyslu? ... Pokud ne, tak budu muset přepracovat celý program a nebo vyloučit možnost umocňování, protože ona je 99%-ní příčinnou problémů. To ovšem dosti znevýhodní program jako celek. Tento program píši už podruhé. První verze Fungovala tak že, vrozce byly umístěné do samostatných souborý které se pak souštěli. Tam nebyl žádný problém je ukončit. Stačilo zavolat "os.system('taskkill /t /f /im "konkretni_vzorec.py"') po určité době. (např. 5 sekund). Od tohoto jsem, ale ustoupil abych celý program zrychlil a navrhl ho tak že už nebude používat žádné mnou vytvořené tempy. Evidentně jsem si vybral špatný programovací jazyk pro svůj problém.
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Matlab - přesnost výpočtu — založil redick
Chyba v jednoduchém výpočtu — založil Roman
Postup u vypočtu složeného vzorce — založil janysek_
Infinity hodnota při výpočtu — založil avalagne
Formulář a zobrazení průběhu výpočtu — založil pifko
Moderátoři diskuze