Forum >> Principianti >> aiuto su multiprocessing o simile

Pagina: 1

Buongiorno, sono nuovo del forum, e della programmazione in generale, ma ancora di più su python. Sto scrivendo il codice per un bot di telegram, ora ho inquadrato il funzionamento, e il bot funziona però in modo errato, perchè, come capirete dal codice, il while true mi impedisce di svolgere qualsiasi altra azione, ora in merito ho letto di multiprocessing di thread, ma non ne riesco a venire a capo, qualcuno disposto a darmi una mano? per contestualizzare incollo il codice.


#!/usr/bin/env python

import pymysql
import telepot

def on_chat_message(msg):
	content_type, chat_type, chat_id = telepot.glance(msg)
	if content_type == 'text':
		name = msg["from"]["first_name"]
		txt = msg['text']
		if '/start' in txt:
			bot.sendMessage(chat_id, 'ciao {}, sono il bot di Automation Service!'.format(name))
		elif 'monitor' in txt:
			while True:
				db = pymysql.connect("localhost","root","root","pippo" )
				cursor = db.cursor()
				cursor.execute("select count(*) from prova where eta > 18")
				((data,),) = cursor.fetchall()
				print("{}".format(data))
				while data!=0:
					print(" sono nel secondo while{}".format(data)) #debug
					bot.sendMessage(chat_id,'allarme')
					time.sleep(5)
				while data==0:
					print("nessun allarme")  #debug 
					bot.sendMessage(chat_id,'nessun allarme')
					time.sleep(5)
		elif '/help' in txt:
			bot.sendMessage(chat_id, 'Ecco i comandi che capisco:\n - /start\n - /monitor')
		else:
			bot.sendMessage(chat_id, 'Mi spiace {}, non capisco\nUsa /help per sapere cosa posso fare!'.format(name))

TOKEN = 'xxxxxxxxxxxxxxxxxxxxxx'

bot = telepot.Bot(TOKEN)
bot.message_loop(on_chat_message)


import time
while 1:
    time.sleep(10)


Questo non è un problema di telegram, è una questione di organizzazione del codice (e di capire come funziona "while", tra l'altro).


Partiamo dai due "while" più interni ("while data..."): primo, che senso hanno? Qui chiaramente volevi scrivere "if data...". E secondo, in ogni caso capisci che non uscirai *mai* da quei cicli, perché "data" resterà sempre uguale, quindi la condizione "while" sarà sempre soddisfatta, una volta entrato nel ciclo.


E poi c'è il "while True" esterno. Anche correggendo i due "while" interni, ovviamente da questo ciclo esterno non puoi più scappare, perché non hai inserito nessuna clausola che eventualmente te ne fa uscire.


Ora, qui devo dire che non capisco la logica del tuo codice: davvero ti interessa "monitorare di continuo all'infinito" non appena arriva il messaggio "monitor"? Perché se è così, ok. Ma allora dovresti anche chiarirti qual è la logica per cui, a un certo punto *smetti* di monitorare. Smetti quando arriva un altro messaggio? E quale? Oppure smetti quando si verifica una certa condizione? E quale? A me viene in mente che forse invece quando arriva "monitor" tu esegui il monitoraggio *una volta sola*, e poi resti in attesa del prossimo messaggio.


Ma se davvero vuoi cominciare a monitorare all'infinito quando arriva il messaggio "monitor", allora (a parte definire una logica per quando deve finire il monitoraggio, come detto) certamente non puoi far partire un ciclo "while True" sincrono, nello stesso thread. Una soluzione sarebbe di mettere questo lavoro di monitoraggio in un thread separato, collegato al thread principale con un Signal in modo che quando è necessario puoi mandare al thread secondario il segnale di terminare il lavoro. Puoi anche collegare i due thread con una Queue, se hanno bisogno di scambiarsi dei messaggi più complessi. Ovviamente devi mettere a punto qualche dettaglio di contorno: per esempio, che cosa succede se arriva un secondo segnale "monitor" quando stai già monitorando? Ovviamente non puoi far partire *un'altro* thread che monitora... altrimenti questa cosa si gonfia come un pallone.


Altre soluzioni passano ovviamente per asyncio... tra l'altro credo che telepot abbia un'api asincrona che potrebbe fare al caso tuo (ma vado a memoria, non saprei).





Detto questo, il problema principale rimane questo: ho paura che non sia conviente affrontare argomenti complessi (tipo, un bot telegram...) se non hai prima imparato a padroneggiare i meccanismi fondamentali del linguaggio (tipo, i cicli while...). Puoi andare avanti ad "adattare" pezzi di codice trovati in giro, ma non farai molta strada, temo.

Grazie per la risposta, conosco il funzionamento dei cicli while ( provengo dal C), e sono a conoscenza del fatto che dai quei cicli non può uscire per nessun motivo, ma in merito ai due cicli interni sono proprio quelli che mi servono, l'if, come da te suggeritomi, mi farebbero solo una volta il "monitor" a me serve che giri sempre, e allora si, sto rifacendo il tutto usando thread separati, ma il dubbio permane, devo utilizzare almeno un while true per far si che una volta richiesto il monitor, lui rimanga attivo fino a diverso comando, che può essere start o help.
nello specifico ho creato un thread che esegue sempre il controllo sul database, ma qualsiasi dato mi faccia restituire devo pur sempre associarlo a una risposta, e supponiamo che dal thread mi faccia ritornare già la risposta, devo pur sempre inviarla al bot ogni intervallo x.
> conosco il funzionamento...

Come vuoi, ma resta il fatto che hai scritto due cicli while che testano una variabile che non viene mai toccata all'interno del ciclo stesso. Quello che hai fatto è:

pastasciutta = 100
while pastasciutta > 0: # questo e' IDENTICO a "while True"
    print('mangio la pastasciutta!')
Se provi questo, vedi che mangi pastasciutta in eterno. Se il tuo ciclo while testa una variabile che poi all'interno del ciclo non viene modificata, i casi sono due: o non entri *mai* nel ciclo, o ci entri e ci resti per sempre. E allora il tuo ciclo è semanticamente uguale a un "while True". Questo non c'entra nulla con telegram o con il tuo problema. E' proprio solo una questione di come funziona "while" (in python, c, pascal, ada, perl, ruby, php, java, c#, quello che vuoi). Dopo un po' che hai imparato come funzionano i cicli while, cose come queste brillano al buio, te ne accorgi subito che c'è qualcosa che non va nel codice che hai scritto.


Dopo di che ti ripeto: *se* la tua idea è di "monitorare per sempre", *allora* la tua idea funziona cambiando i due "while" interni con degli "if" e lasciando solo il "while" esterno. Se ti metti con carta e penna a seguire il flusso del programma, lo vedi chiaramente. Dopo di che, certo, dovresti ancora risolvere il problema del "while" esterno che blocca il programma. E per questo, se vuoi, puoi usare i thread, o multiprocessing, o una soluzione asincrona... Ma è un altro problema.






Pagina: 1



Esegui il login per scrivere una risposta.