RISOLTO UnboundLocalError python

Pubblicità
Stato
Discussione chiusa ad ulteriori risposte.

Hero467

Utente Attivo
Messaggi
695
Reazioni
406
Punteggio
75
Salve a tutti,
sto scrivendo un bot telegram per diletto, e mi sono trovato davanti questo problema:
Codice:
Traceback (most recent call last):
  File "/home/ricky/.local/lib/python3.10/site-packages/telegram/ext/dispatcher.py", line 557, in process_update
    handler.handle_update(update, self, check, context)
  File "/home/ricky/.local/lib/python3.10/site-packages/telegram/ext/handler.py", line 199, in handle_update
    return self.callback(update, context)
  File "/home/ricky/Scrivania/Coding/bot.py", line 18, in rispondi
    case 'ciao': res_ciao()
  File "/home/ricky/Scrivania/Coding/bot.py", line 27, in res_ciao
    match ciao_counter:
UnboundLocalError: local variable 'ciao_counter' referenced before assignment

Io la variabile in questione l'ho inizializzata prima della dichiarazione della funzione, quindi non capisco il problema.

Codice:
Python:
from random import *
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters

TOKEN = 'CENSURA'

ciao_counter = 0
ciao_list = ['ciao', 'ehi', 'sciao', 'hello', 'hola', 'bonjour']

def start(update, context):
    update.message.reply_text('''
    Ciao
    ''')

def rispondi(update, context):
    msg = update.message.text.lower()
    match msg:
        case 'ciao': res_ciao()


updater = Updater(TOKEN)
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(MessageHandler(Filters.text, rispondi))
updater.start_polling()

def res_ciao():
    match ciao_counter:
        case 0:
            updater.message.reply_text(choice(ciao_list))
            ciao_counter += 1
        case _:
            updater.message.reply_text('...')
 
Ultima modifica:
Ammetto di non capirci nulla, ma nello stesso tempo ti invio
 
Immagino che la parte non chiara sia quella che comprende le istruzioni della libreria
 

Oppure lo passi come argomento alla funzione
 
Non è sbagliato renderla globale, ma di norma nella programmazione le variabili globali vanno usate solo dove strettamente necessario, dove non puoi evitarlo. Sarebbe meglio un parametro, e restituire poi il valore (visto che in Python non mi sembra esista il passaggio per riferimento).
 
Il problema si è ripresentato, ma stavolta con una funzione.
Per praticità ho creato una funzione che sostituisse update.message eccetera, sempre dentro la funzione rispondi:
Python:
def printmsg(text):
    update.message.reply_text(text)

ma mi dice comunque la stessa cosa di prima

edit: ah, ho trasferito il contenuto di res_ciao() in rispondi(), per problemi di parametri, quindi adesso è così:
Python:
def rispondi(update, context, ciao_counter=0):
    msg = update.message.text.lower()
    case 'ciao':
        match ciao_counter:
            case 0:
                printmsg('ciao')
 
Ultima modifica:
Pubblica il codice intero, il problema è che nello scope dove usi quella variabile, non esiste. Prova a dichiararla globale come suggerito da Dumah, così capisci qual è il problema.
 
Il problema è che è una funzione, non una variabile. Mi fa strano questo
Pubblica il codice intero
Si giusto, scusa


Python:
# LIBRARIES
from random import *
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters



# CONSTANTS & VARIABLES
TOKEN = 'CENSURA'

ciao_counter = 0
ciao_list = ['ciao :)', 'ehi', 'sciao', 'hello', 'hola', 'bonjour']

adopo_list = ['a dopo :)', 'sciaoo', 'adios', 'gudbai', 'ciao :)']








def start(update, context):
    update.message.reply_text('''
    Ciao
    ''')

def reply(update, context, ciao_counter=0):
    msg = update.message.text.lower()
    match msg:
        case 'ciao':
            match ciao_counter:
                case 0:
                    printmsg(choice(ciao_list))
                    ciao_counter += 1
                case 1:
                    printmsg('Mi hai già salutato, non serve che lo fai di nuovo')
                    ciao_counter += 1
                case 2:
                    printmsg('Mi. hai. gia. salutato')
                    ciao_counter += 1
                case 3:
                    printmsg('Basta, non ti rispondo più')
                    ciao_counter += 1
                case _:
                    printmsg('...')
       
        case msg if 'a dopo' in msg:
            printmsg('a dopo :)')
            ciao_counter = 0

        case _:
            printmsg('Eh?')





    def printmsg(text):
        update.message.reply_text(text)


updater = Updater(TOKEN)
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(MessageHandler(Filters.text, rispondi))
updater.start_polling()
 
... Sarebbe meglio un parametro, e restituire poi il valore (visto che in Python non mi sembra esista il passaggio per riferimento).
Piu' o meno. Ogni variabile in Python e' in realtà considerata un oggetto, e gli oggetti sono di due categorie "mutable" (ossia che possono cambiare, per esempio una lista) e "immutabile" (il cui valore non può cambiare, per esempio una stringa). Per questo in Python non esiste il concetto di passaggio per valore o per riferimento, dipende se l'oggetto e' immutabile o meno. Uno dei problemi di chi arriva a Python da linguaggi tipo C che NON sono "dynamically typed" (non so come si dica in italiano). Ed e' anche uno dei problemi nel usare Python come linguaggio per imparare: non e' cosi' semplice come si possa credere.
 
Ed e' anche uno dei problemi nel usare Python come linguaggio per imparare: non e' cosi' semplice come si possa credere.
Confermo, infatti continuo a non riuscire a risolvere, mi tratta ancora la funzione come una variabile. E su internet non c'è nulla di utile se non quello che è stato già scritto qui
 
Piu' o meno. Ogni variabile in Python e' in realtà considerata un oggetto, e gli oggetti sono di due categorie "mutable" (ossia che possono cambiare, per esempio una lista) e "immutabile" (il cui valore non può cambiare, per esempio una stringa). Per questo in Python non esiste il concetto di passaggio per valore o per riferimento, dipende se l'oggetto e' immutabile o meno. Uno dei problemi di chi arriva a Python da linguaggi tipo C che NON sono "dynamically typed" (non so come si dica in italiano). Ed e' anche uno dei problemi nel usare Python come linguaggio per imparare: non e' cosi' semplice come si possa credere.

Mi sono fatto contagiare dal virus del "tuttologo", visto che non conosco Python. ? So che Python usa l'inferenza per determinare il tipo di una variabile comunque, come fa Rust quando non specifichi un tipo (solo che avviene in compile time qui).

Confermo, infatti continuo a non riuscire a risolvere, mi tratta ancora la funzione come una variabile. E su internet non c'è nulla di utile se non quello che è stato già scritto qui

Ma dal tipo di errore io non penso proprio che ti stia trattando la funzione come una variabile invece.

UnboundLocalError: local variable 'ciao_counter' referenced before assignment

se l'eccezione che hai è ancora questa, la soluzione è quella che ti è stata data da Dumah o cdtux.

Non ho capito dove stai usando la funzione "reply". E' una sorta di callback immagino, no? Se è così, qui stai chiamando una funzione che non esiste:

Codice:
updater.dispatcher.add_handler(MessageHandler(Filters.text, rispondi))

Anche quel counter, secondo me lo stai usando nella maniera sbagliata. Prova a fare quanto indicato da Dumah.
 
Il problema è che è una funzione, non una variabile. Mi fa strano questo

Si giusto, scusa


Python:
# LIBRARIES
from random import *
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters



# CONSTANTS & VARIABLES
TOKEN = 'CENSURA'

ciao_counter = 0
ciao_list = ['ciao :)', 'ehi', 'sciao', 'hello', 'hola', 'bonjour']

adopo_list = ['a dopo :)', 'sciaoo', 'adios', 'gudbai', 'ciao :)']








def start(update, context):
    update.message.reply_text('''
    Ciao
    ''')

def reply(update, context, ciao_counter=0):
    msg = update.message.text.lower()
    match msg:
        case 'ciao':
            match ciao_counter:
                case 0:
                    printmsg(choice(ciao_list))
                    ciao_counter += 1
                case 1:
                    printmsg('Mi hai già salutato, non serve che lo fai di nuovo')
                    ciao_counter += 1
                case 2:
                    printmsg('Mi. hai. gia. salutato')
                    ciao_counter += 1
                case 3:
                    printmsg('Basta, non ti rispondo più')
                    ciao_counter += 1
                case _:
                    printmsg('...')
     
        case msg if 'a dopo' in msg:
            printmsg('a dopo :)')
            ciao_counter = 0

        case _:
            printmsg('Eh?')





    def printmsg(text):
        update.message.reply_text(text)


updater = Updater(TOKEN)
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(MessageHandler(Filters.text, rispondi))
updater.start_polling()

Il ciao_counter o lo usi come global, o lo passi come parametro quando usi la funzione. Il problema è che per come hai scritto il codice, non stai effettivamente passando la variabile ciao_counter come parametro (o quantomeno dal codice che hai postato non si vede).
Per evitare confusione, sarebbe meglio cambiare il nome del parametro del counter della funzione reply.
Ti faccio un esempio per spiegarmi meglio:
Python:
ciao_counter = 0
def reply(update, context, counter = 0):
    print(counter)
    counter +=1
    print(counter)
# qui passo come parametro la variabile ciao_counter alla funzione reply
reply('A', 'B', ciao_counter)

# qui sto usando ciao_counter come global all'interno della funzione reply
def reply2(update, context):
    global ciao_counter
    print(ciao_counter)
    ciao_counter += 1
    print(ciao_counter)
reply2('E', 'F')

Anche io ho il dubbio che stai usando questo counter in modo sbagliato.
Questo fantomatico counter, ti serve solamente all'interno della funzione reply o deve essere utilizzato anche in altre parti del programma?? In tal caso, deve avere un valore aggiornato o deve ripartire da 0 ogni volta che lo utilizzi??
 
Grazie per le risposte.
ciao_counter l'ho sistemato passandolo come variabile globale (se lo passavo come parametro mi si resettava ogni messaggio, rendendolo così inutile), e lì tutto sistemato.
Errore mio è stato non mettere il messaggio di errore nuovo, che indicava la stessa cosa del precedente, solo che lo diceva sulla funzione 'printmsg'. Ho comunque risolto, il problema era che avevo chiamato la funzione prima della sua dichiarazione. Solo una cosa mi fa strano: il fatto che sugli altri linguaggi basta che la funzione la dichiari, non importa quando e dove, per questo io l'ho dichiarata alla fine per pulizia del codice.
--- i due messaggi sono stati uniti ---
Non ho capito dove stai usando la funzione "reply". E' una sorta di callback immagino, no? Se è così, qui stai chiamando una funzione che non esiste:

Codice:
updater.dispatcher.add_handler(MessageHandler(Filters.text, rispondi))
Errore mio, nel codice che ho postato avevo dimenticato di cambiare 'rispondi' in reply, che ho tradotto per coerenza. Stessa cosa ho fatto con le variabili
 
Stato
Discussione chiusa ad ulteriori risposte.
Pubblicità
Pubblicità
Indietro
Top