Topic: Salvare Variabili con Pickle dentro for loop  (Letto 140 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline riemann code

  • python unicellularis
  • *
  • Post: 2
  • Punti reputazione: 0
    • Mostra profilo
Salvare Variabili con Pickle dentro for loop
« il: Dicembre 23, 2019, 22:17 »
sto leggendo dei dati di un sensore ed ho bisogno di salvarli. Il codice relativo alla lettura dei dati del sensore si trova dentro il for loop (infinito perché legge in continuazione i dati).

Ho provato a simulare dei dati con random(), come se fossero i dati del sensore.

questo è il codice.


import pickle
from random import random
from itertools import count

array2 = []


for i in count():


    x = random()
    array2.append(x)


    print(array2[i])
    pass


pickle_out = open("Simulation.pickle","wb")
pickle.dump(array2, pickle_out)
pickle_out.close()



Sto utilizzando pycharm e anche runnando la console quando fermo lo script (mettiamo che ho collezionato abbastanza dati), mi ritrovo senza nessun dato salvato.
Se invece lancio questo stesso codice ma con un loop finito (mettiamo caso range(0,100) pickle mi salva "la simulazione".

La mia idea sarebbe: creare un modo per bloccare il for loop ad esempio con un if statement (di fatto riproducendo l'esempio con il loop finito range(0,100)) e riuscire ad accedere alla parte finale del codice che mi permette di salvare la simulazione.

Premetto che ho poca esperienza programmando in generale quindi non saprei proprio come muovermi.
Come posso salvare i dati?
Ci sono delle strade più ottimali di quella che sto percorrendo?

Grazie   :caffè:

Offline nuzzopippo

  • python erectus
  • ***
  • Post: 188
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare Variabili con Pickle dentro for loop
« Risposta #1 il: Dicembre 24, 2019, 08:14 »
Sto utilizzando pycharm e anche runnando la console quando fermo lo script (mettiamo che ho collezionato abbastanza dati), mi ritrovo senza nessun dato salvato.

Non ho mai utilizzato pycharm, comunque, supposto Tu lo interrompa tastiera dovresti intercettare l'evento di interruzione tramite la sua eccezione, esmpio sul Tuo codice _

Python 3.6.9 (default, Nov  7 2019, 10:44:02)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license()" for more information.
>>> import pickle
>>> from random import random
>>> from itertools import count
>>> array2 = []
>>> for i in count():
try:
x = random()
array2.append(x)
print(array2[i])
except  KeyboardInterrupt:
break

In questo modo il programma non verrebbe interrotto ed i dati potrebbero essere memorizzati ... ovviamente, se l'interruzione in pycharm Ti da una eccezione diversa da KeyboardInterrupt dovresti utilizzare quella.
[Edit] dimenticavo, il mancato "salvataggio" dei dati è dovuto all'interruzione non intercettata che blocca completamente il programma, intercettandola nel codice, invece, si può procedere in merito.

Detto questo :
1° - per fare un ciclo infinito utilizza un "while True", invece di "for i in count()";
2° - memorizzare variabili in un ciclo infinito Ti porta, inevitabilmente, ad un out-of-memory, la ram non è infinita e nemmeno lo spazio su disco.

Ovviamente, non ho idea cosa servano i dati del sensore e la frequenza che gli stessi abbiano ma Ti suggerirei, comunque, di rivedere e valutare le Tue necessità ... l'infinito è, per definizione, troppo grande.

Per quanto riguarda la "ricezione" di un set limitato di dati, basterebbe inserire un contatore, esempio basato sempre sul Tuo codice ma con while:
>>> array2 = []
>>> count = 0
>>> from random import random
>>> while True:
x = random()
array2.append(x)
print(x)
count += 1
if count >= 10:
break


0.9024611194693071
0.6971271599765463
0.7844673426363536
0.4398330372665694
0.016445834885608024
0.026536825069656822
0.031420142463974066
0.9470985058025532
0.6831810443230643
0.6155463183919491
>>> print(array2)
[0.9024611194693071, 0.6971271599765463, 0.7844673426363536, 0.4398330372665694, 0.016445834885608024, 0.026536825069656822, 0.031420142463974066, 0.9470985058025532, 0.6831810443230643, 0.6155463183919491]
>>>


Ci sono strade più ottimali? ... su questo lascio la parola ad utenza più esperta, non pratico "sensori", in ogni caso credo che bisogni agire sulla base delle caratteristiche dell'oggetto da trattare e degli obiettivi da raggiungere, dato che piccole "varianti" possono dare profonde modifiche a ciò che si deve fare.

[Ri-Edit] sul "come posso salvare i dati" ... il dump di pickle è buono come qualsiasi altro tipo scrittura su file, il "come" dipende dalle finalità da raggiungere e dal contesto applicativo da rispettare ... suggerirei, se possibile, di acquisire, con calma, le basi del linguaggio e poi approfondire il contesto di interesse, poi ri-valutare il problema.
« Ultima modifica: Dicembre 24, 2019, 08:24 da nuzzopippo »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.972
  • Punti reputazione: 9
    • Mostra profilo
Re:Salvare Variabili con Pickle dentro for loop
« Risposta #2 il: Dicembre 24, 2019, 12:33 »
> suggerirei, se possibile, di acquisire, con calma, le basi del linguaggio e poi approfondire il contesto di interesse, poi ri-valutare il problema

Sì, questo è decisamente il consiglio giusto.
Dimenticare il tuo problema specifico per almeno sei mesi (meglio un anno) e seguire nel frattempo un buon libro passo-passo (il Lutz è sempre una buona idea). Ovviamente questa è anche l'unica idea che *nessun* principiante prende neanche lontanamente in considerazione, ci mancherebbe. Però è anche l'unica buona idea, quindi per ragioni etiche bisogna sempre, tutte le volte, almeno metterla a verbale.

Quello che stai cercando di fare non ha senso sotto praticamente nessun aspetto che mi venga in mente.
Il problema di partenza "voglio fare un programma con un sensore, ma adesso non ho un sensore fisicamente disponibile, quindi voglio simularlo" di per sé è assolutamente valido, ci mancherebbe. Però da qui in poi, frana tutto.
Per prima cosa: un sensore è un aggeggio che tipicamente invia dei dati su una porta predefinita. Non è "dalla stessa parte" del tuo programma. E' un *altro* programma, *separato* dal tuo, che gira in continuazione *indipendentemente* dal tuo (magari sulla stessa macchina e stesso sistema operativo, magari anche su una macchina diversa usando un web socket... ma non facciamo troppe distinzioni). Quindi, se la tua intenzione è quella di simulare la ricezione dei dati che emetterebbe un sensore, non ha nessun senso scrivere un programmino che si genera da solo i suoi dati e se li consuma... in qualunque modo tu faccia, con un ciclo infinito, con "count", con "range"... non ha nessun senso perché se avessi davvero un sensore, quello starebbe comunque *fuori* dal tuo programma e non dentro. Quello che dovresti fare è scrivere un programmino "server" che genera periodicamente dei dati e li scrive su un socket, poniamo, e va avanti così all'infinito. E poi, dall'altra parte, scrivere il "tuo" programmino, che ascolta quel socket all'infinito e, man mano che arrivano i dati, li processa in qualche modo.
Ora, naturalmente al limite questo potrebbe anche essere fatto con "un solo" programma multithreading o (meglio, visto il tipo di aggeggio che stai andando a simulare) multiprocessing. Ma in ogni caso si tratta di *due* processi (o almeno thread di esecuzione) distinti, non di uno solo. (Mi rendo conto che tutto questo è un po' arabo... ma è per farti capire che il consiglio-che-nessun-principiante-segue è anche il consiglio giusto... non ci sono scorciatoie).

Poi, in seconda battuta, dovresti capire che cosa vuoi farci davvero, con questi dati. Qual è la logica di processamento. Questo però non è nemmeno un problema di programmazione o di sapere Python... questo è proprio solo un problema di capire che cosa si vuol fare. Un sensore, tipicamente, emette dati virtualmente all'infinito. La tua logica non può essere "li raccolgo tutti e... <faccio qualcosa>" perché per definizione non *puoi* raccoglierli tutti... sono infiniti, capisci? Invece, puoi farci il tipo di operazioni che di solito si fanno con un flusso di dati infinito... ma devi decidere tu. Per esempio, può avere senso "scriverli in un file" (a parte l'uso di pickle che invece potrebbe o no avere senso... probabilmente no, ma lasciamo stare... stai usando strumenti a casaccio raccattati in giro...). Ma allora dovresti per esempio tenere il file aperto e accodarli man mano che arrivano... o magari decidi che ne raccogli un tot in un "buffer" (una lista, va a sapere) e li scrivi tutti di colpo (diciamo, 100 per volta). Ma in ogni caso devi attrezzarti per gestire un numero infinito di dati in arrivo.
Questo, ripeto, è un problema di logica prima ancora che di programmazione. Non è troppo difficile arrivare a scrivere un programmino che ha un thread "producer" che, diciamo, mette a intervalli regolari dei numeri in una Queue, e un thread "consumer" che a intervalli regolari legge e svuota la Queue. Questa è la meccanica di base, e se vuoi è già una simulazione "decente" (in realtà... boh, quasi) della meccanica del tuo sensore. Dopo di che, tuttavia, il tuo "consumer" si ritrova con un un ciclo eterno del tipo

def consumer(queue):
    while True:
        item = queue.get()
        if item:
            process_item(item) # <---- e QUI STA IL PUNTO
        queue.task_done()

E mi rendo conto che questo per te è di nuovo arabo (ma come dicevo, non ci sono scorciatoie) ma il punto è che devi capire che cosa fa, tutte le volte, "process_item" considerando il fatto che potrebbe essere chiamata un numero infinito di volte. Qui ti si aprirebbero altri problemi tecnici, ovviamente (per esempio: che cosa succede se "process_item", che è bloccante, impiega un tempo lungo? posso permettermi di bloccare la coda nel frattempo, oppure ho bisogno di "processamento in tempo reale"? Allora devi impostare un meccanismo asincrono dietro a questo, etc.).
Ma prima di tutto i problemi sono di tipo logico, non tecnico. Al limite potresti anche pensare di "simulare" (malissimo) i tuoi dati infiniti "nello stesso processo", senza ricorrere a niente della meccanica che davvero ti serve (processi separati, bla bla bla), un po' come stavi tentanto di fare... Basta usare un ciclo while True infinito come ti è stato mostrato, senza passare per itertools.count che non aggiunge niente di interessante.

def counsumer():
    while True:
        item = random.randint(1, 100) # per dire
        process_item(item)

def process_item(item):
    pass # <------- e qui sta il punto

consumer()

Qui "consumer" è solo la meccanica della produzione di dati (implementata malissimo, ma tant'è). Il problema però è la logica che vuoi mettere dentro "process_item", che deve trattare con un flusso di dati infinito.

Offline riemann code

  • python unicellularis
  • *
  • Post: 2
  • Punti reputazione: 0
    • Mostra profilo
Re:Salvare Variabili con Pickle dentro for loop
« Risposta #3 il: Dicembre 29, 2019, 19:06 »
scusami RicPol ma non ho tempo di scrivere un papiro nè di fare sofismi. Risponderò per punti

1) il codice funziona e riesco ad acquisire i dati dal mio sensore reale (DHT11) ed a salvarli con Pickle
1.1) grazie per la lezione sui sensori e sulla parentesi della generazione infinita di dati, l'ho apprezzata.

2) Quando ne ho "abbastanza di dati" (misuro l'umidità e temperatura di una cantina, non lavoro al CERN), clicco ctrl+c che mi blocca la console.
Dopo che ho bloccato la console evidenzio la parte finale di codice relativa a Pickle, e la lancio singolarmente con alt+MAIUSC+E (pyCharm).
A questo punto i dati sono salvati. e posso "farne qualcosa".

3) Farne qualcosa di abbastanza dati. Ci posso fare: una regressione lineare, un Vector Auto Regressive (con matrice di Cholesky), un filtro di Kalman, un disegno su paint.

4) Vero che i principainti non leggono lo Lultz e non aspettano un anno.
4.1) Vero che acquisirò le basi (guidare la ferrari con la patente del monopattino non va bene).

5) A parte l'ironia di qualche punto precedente apprezzo l'aiuto datomi.
5.1) La burocrazia è nemica dell'efficienza/praticità.


Buone feste a tutti :birrame: :birrame: