Topic: Flask - Esempio "Flaskr" e connessione al Database con SQLite3  (Letto 1559 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline AliceForgotten

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Ciao a tutti!

Ho iniziato un progetto in Python per la costruzione di una web app che si occupa di richiedere alcuni files in JSON da alcuni web services specifici, mostrarne il contenuto tramite una GUI, gestirne il contenuto tramite suddetta GUI ed infine dopo N elaborazioni, salvare il contenuto nel DB (MySQL).

Piattaforma: Windows
Tecnologie: Python + MySQL

Un'amica mi ha consigliato Flask, utilizzato da un suo collega molto esperto a riguardo.

Sto implementando il test seguente:
http://flask.pocoo.org/docs/0.10/tutorial/dbinit/#tutorial-dbinit
trovato proprio sul sito web di Flask.

Sono arrivata allo [Step 3: Creating The Database] e mi sono malauguratamente bloccata, senza dubbio a causa di qualche mia mancanza conoscitiva di base.
Non sono un programmatore alle prime armi, eppure c'è qualcosa che mi sfugge, per quanto banale possa essere.

Nello specifico, quando effettuo l'operazione richiesta verso la fine:
[codice]>>> from flaskr import init_db
>>> init_db()
[/codice]

Genera il seguente errore:
[codice]Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    init_db()
  File "C:manmadevenvflaskrflaskr.py", line 23, in init_db
    with closing(connect_db()) as db:
  File "C:manmadevenvflaskrflaskr.py", line 20, in connect_db
    return sqlite3.connect(app.config['DATABASE'])
sqlite3.OperationalError: unable to open database file
[/codice]

Il codice finora creato, segue unicamente la guida (non l'ho scaricato da GitHub, volevo un tutorial passo passo appositamente):
[codice]# all the imports
import sqlite3
from flask import Flask, request, session, g, redirect, url_for,
     abort, render_template, flash
from contextlib import closing

# configuration
DATABASE = '/tmp/flaskr.db'
DEBUG = True
SECRET_KEY = 'development key'
USERNAME = 'admin'
PASSWORD = 'default'


# create our little application :)
app = Flask(__name__)
app.config.from_object(__name__)

def connect_db():
    return sqlite3.connect(app.config['DATABASE'])
   
def init_db():
    with closing(connect_db()) as db:
        with app.open_resource('schema.sql', mode='r') as f:
            db.cursor().executescript(f.read())
        db.commit()
   
if __name__ == '__main__':
    app.run()[/codice]

Premetto che:
- ho solamente il file .sql
- tutto l'environment funziona, su localhost:5000
- non ho il file .db
- non ho settato il DB sulla MySQL Workbench

Cosa mi sono persa?
Mi è venuto il sospetto di dover settare il DB sulla MySQL Workbench, ma siccome nel tutorial non era citato ho pensato facesse qualche magia: mi sbaglio?

Grazie  :) :) :) :question:

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.876
  • Punti reputazione: 9
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #1 il: Febbraio 20, 2015, 13:15 »
Sì beh il problema con questo genere di tutorial è che in genere presuppongono che tu abbia comunque una minima competenza con python (per esempio saper leggere e interpretare una stacktrace), e in generale con gli strumenti che stai usando (a partire dal sistema operativo e dal suo file system, in questo caso specifico). Altrimenti uno può anche ricopiare scrupolosamente tutte le righe del codice proposto, ma questo non è garanzia che le cose funzioneranno davvero... e anche se funzionano, uno non capisce perché funzionano.

Ora, questo è di sicuro un tutorial scritto da qualcuno su una linux box. Ma banalmente una path come /tmp/whatever in windows non esiste (perché in windows le path funzionano in modo diverso). Specifica una path più "normale", diciamo così, per il mondo windows, in cui ficcare il tuo db.

Offline AliceForgotten

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #2 il: Febbraio 20, 2015, 14:36 »
Ah, ok, perfetto!
Programmare in Python -> ok, anche se non livello ottimo.
Avere a che fare col SO -> not ok, in particolare i path vari e compagnia bella, non sono per niente esperta.
Provo a smaneggiare sul path allora :) grazie!

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.876
  • Punti reputazione: 9
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #3 il: Febbraio 20, 2015, 19:21 »
Programmare in Python -> ok, anche se non livello ottimo.
Allora, prima di tutto si guarda sempre che cosa dice la stacktrace: unable to open database file, nel momento in cui sta eseguendo l'istruzione sqlite3.connect(app.config['DATABASE']) .
Siccome l'istruzione di per sé è elementare, si guarda _quale_ "database file" sta cercando di aprire, e si scopre che app.config['DATABASE'] vale '/tmp/flaskr.db' . Ora, se proprio già non viene un campanello di allarme a vedere in windows una path del genere, si cerca di capire con pazienza che cosa succede... si apre una shell, e si dice
[codice]
>>> import sqlite3
>>> sqlite3.connect('/tmp/flaskr.db')
[/codice]
e si vede che dà lo stesso errore... allora si prova (solo come sanity check) a fare >>> sqlite3.connect('flaskr.db') (e questo ovviamente funziona), e si capisce che ci deve essere un errore nella path... ma quale? Forse che la path /tmp/ non esiste? e si fanno altre verifiche.

Questo sarebbe "programmare in python". Poi certo, con il tempo queste cose si impara a vederle un po' a occhio, e questi test si fanno spesso a mente... ma questo diventa già "programmare in python a livello intermedio".

Offline AliceForgotten

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #4 il: Febbraio 23, 2015, 11:13 »
Capisco.
Beh, era l'errore più logico.
Quello che mi chiedevo non era se il path fosse giusto di per sé, ma se il path avesse un significato "assolutistico" di path generico (oppure se lo creasse da sé ad esempio, facendo le suddette magie).
Ho lunga esperienza come programmatore in C, livello piuttosto avanzato (programmazione parallela su GPU), e chiaramente so una dozzina di linguaggi ;)
In PY conosco molto bene l'uso delle RE per parsare il testo e il codice (anche in altri linguaggi) e per computazioni logico matematiche.

Detto questo, il debug non mi è certo nuovo.
Pensavo solamente che PY per il Web (Flask, poi nello specifico - premetto che sono esperta in PHP) fosse maggiormente "intelligente", ma è evidente che non sia così ;)

Offline juliux

  • python unicellularis
  • *
  • Post: 28
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #5 il: Febbraio 23, 2015, 11:51 »
Sì, che è un po' come dire che se, in una shell di python3 digiti questo:

[codice]>>> print("kitten")[/codice]

tu ti aspetti che improvvisamente dalla stampante esca un felino  :).

Potresti essere super-esperta pure di ingeneria aero-spaziale, ma lo accetti un consiglio da un umile ignorante come me? Se vuoi usare Python con successo, comincia dallo stamparti questo: appendilo in camera, leggilo ogni mattina, contemplalo ogni sera e adoralo come una scrittura sacra.

Offline AliceForgotten

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #6 il: Febbraio 23, 2015, 12:06 »
Molto interessante, le risposte di questo forum virano sempre verso uno frustrato "arrangiati" che mi mette tanta compassione.

Quando troverò il maledetto Path che mi serve, posterò qui la soluzione, così che qualche altro malcapitato non debba sorbirsi innumerevoli prese per il c**o, come se fossero tutti nati scienziati (ma bravo tu, eh, bravo tu)! Lavori presso Google, spero ;)

Hardware Upgrade docet ;) ;) c'è ancora molto da imparare (o da insegnare?)

Offline juliux

  • python unicellularis
  • *
  • Post: 28
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #7 il: Febbraio 23, 2015, 12:11 »
Molto interessante, le risposte di questo forum virano sempre verso uno frustrato "arrangiati" che mi mette compassione.

Beh, io non posso parlare per gli altri, ma quando chiedo qualcosa io, preferisco che mi si venga illustrato un percorso e non la soluzione diretta.
Si impara di più e si sviluppa una propria indipendenza, anche nel reperire autonomamente le risorse necessarie.

Quando troverò il maledetto Path che mi serve, posterò qui la soluzione, così che qualche altro malcapitato non debba sorbirsi innumerevoli prese per il c**o, come se fossero tutti nati scienziati (ma bravo tu, eh, bravo tu)!

Il mio era un sincero consiglio, forse un po' spinto all'estremo, ma pur sempre un consiglio. Mi dispiace che non sia stato interpretato come tale.

Offline AliceForgotten

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #8 il: Febbraio 23, 2015, 12:20 »
;) un consiglio pressoché banale.

Siccome non sono uno studente, preferisco la soluzione diretta: imparo per esempi, come ogni buon programmatore ad un certo livello della sua carriera.

Stack Overflow no? Si pone il problema, si trova (possibilmente) la soluzione. Non penso sia un giochino stile indovina indovinello. Presumo ;)

Appena la trovo, se nessuno la conosce direttamente, la posto. E' una promessa per ogni nuovo sventurato ;)
« Ultima modifica: Febbraio 23, 2015, 12:22 da AliceForgotten »

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.876
  • Punti reputazione: 9
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #9 il: Febbraio 23, 2015, 12:46 »
juliux, questo era innecessariamente brusco.

alice, il fatto è che fa un po' sorridere che una persona con "lunga esperienza di programmazione C" e una dozzina di linguaggi, etc., non abbia chiaramente idea di come è fatta una path.

Questo non ha assolutamente niente a che vedere con la "stupidità/intelligenza" di Flask. Se tu immagini che in windows "di regola" esiste una path come "/tmp", allora avrai problemi in Flask e in quasi tutti i task di programmazione che possono venirmi in mente su due piedi (almeno, in windows...).
Poi uno con l'esperienza ci fa subito l'occhio (per esempio: l'esperienza insegna che la stragrande maggioranza delle doc in giro sono fatte su piattaforme linux e "pensando" per utenti linux... chi usa windows deve sempre fare un po' di traduzione al volo qua e là... dopo un po' ti viene automatico).

Se vuoi, naturalmente, puoi anche chiederlo: che cosa vuol dire la path "/tmp"? Che cosa vuol dire quel "/" iniziale? Perché in windows questa path "di regola" non c'è?
E, anche se naturalmente si va off topic, qualcuno ti risponderà.

Offline AliceForgotten

  • python unicellularis
  • *
  • Post: 7
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #10 il: Febbraio 23, 2015, 12:57 »
Ti rispondo a tono: in C, come in tanti altri linguaggi ma soprattutto in C, se un path non esiste lo crea in automatico se in scrittura :) pensavo la magia fosse la medesima ;) si sa mai, con nuovi sistemi innovativi e quanto altro :-3 ma non credevo di dover postare il mio CV dopo una banalissima domanda (alla quale ancora non ho avuto una risposta chiara, semplice e diretta).
Se volevo instaurare una discussione presso gruppi di flamers, avrei aperto un post su qualche forum apposito.

No, in quanto a SO in sé il concetto di PATH mi è sempre stato abbastanza ostico, non ho avuto abbastanza da sbatterci la testa (a parte litigi con il prompt dei comandi, files in lettura/scrittura, e cose piuttosto banali) - ma è una cosa che ho detto fin dall'inizio, e se volessi sbatterci la testa lo farei per bene e con oculato studio.

Il fatto che molti esempi siano soprattutto in Linux mi fa pensare: ma il tempo di costruire una guida altrettanto semplice per Win, no?
Cos'era, troppo poco figo? Il 91% dei progetti Desktop è Windows-based, maledizione, NON è un numero ignorabile (scusate il maiuscolo ma ce voleva).

Nel frattempo, dopo aver perso tempo nel NULL più assoluto, ho trovato la mia medesima domanda qui (dopo 40mila ricerche):
http://stackoverflow.com/questions/15740964/stuck-at-flask-tutorial-step-3
spero che a qualcuno sia utile e risparmi tempo in inutili discussioni autoreferenzianti ;)

Offline riko

  • python deus
  • *
  • moderatore
  • Post: 7.453
  • Punti reputazione: 12
    • Mostra profilo
    • RiK0 Tech Temple
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #11 il: Febbraio 23, 2015, 16:07 »
Ti rispondo a tono: in C, come in tanti altri linguaggi ma soprattutto in C, se un path non esiste lo crea in automatico se in scrittura

Credo che io e te abbiamo usato versioni diverse del linguaggio. :)

Ora, per essere completamente sinceri lo standard dice che le regole per definire un file name valido sono implementation defined.
In pratica, quando prendi una qualunque implementazione scopri che parecchie cose sono in comune.

Per esempio dal man di fopen, menziona che puo' fallire per le stesse ragioni per cui puo' fallire (fra le altre), open(2).
In particolare, quando chiami fopen (o open) quello che puo' succedere e' che manca qualche componente del path.
Giusto per il povero cristo che leggera' questa discussione nel futuro (tu probabilmente lo sai) quando questo succede ti trovi errno settato a

OS X:
     [ENOENT]           A component of the path name that must exist does not exist.
Linux:
       ENOENT O_CREAT is not set and the named file does  not  exist.   Or,  a
              directory  component in pathname does not exist or is a dangling
              symbolic link.

A sboccio direi che anche su Windows ti trovi ENOENT, sebbene potrebbe essere una condizione diversa. Ma mi aspetto che ti trovi comunque un errore.

Ovvero in C non puoi aspettarti che open("/this/path/file") funzioni a meno che /this/path non sia gia' il path di una directory (se e' un file, ti peschi ENOTDIR ). Poi ovviamente ci sono tutta una serie di altri motivi non rilevanti in questo caso per cui la cosa potrebbe fallire.

Quindi *non* e' vero che C ha il comportamento che sostieni avere. E in effetti quando in Python fai open (che e' quello che sotto il cofano fa connect quando gli passi un path locale), sotto ancora viene chiamata proprio fopen. Poi certo, errno viene mandruppato nell'eccezione, ma non e' che cambia troppo.

Citazione
:) pensavo la magia fosse la medesima ;) si sa mai, con nuovi sistemi innovativi e quanto altro :-3

Si, la "magia" e' la stessa: la magia che asserisci non esiste; per lo meno, non esiste sulla maggior parte dei sistemi su cui ho messo mano.

> ma non credevo di dover postare il mio CV dopo una banalissima domanda (alla quale ancora non ho avuto una risposta chiara, semplice e diretta).

Guarda che "postare il CV" e' stata una scelta tua. E la risposta l'hai avuta, anche se probabilmente non sufficientemente chiara.

Provo ad essere piu' chiaro io: quello che ti hanno detto e'

Hai un errore perche' il path che specifichi non e' valido. Probabilmente non esiste la directory /tmp (ovvero C:   mp -- un minimo di magia su / e  viene tipicamente fatta dalla libc, cui Python si rifa' interamente -- nel senso che chiama fopen, quello che va bene per fopen va bene per Python). Se esiste, potresti non avere i permessi opportuni.

Prendi un path valido (il tuo sistema lo conosci tu e sei la persona piu' indicata per farlo) e dovrebbe funzionare. Se hai ancora dubbi, puoi sempre fare una open (python) del file, catturare l'eccezione e vedere che dice errno.


Citazione
Se volevo instaurare una discussione presso gruppi di flamers, avrei aperto un post su qualche forum apposito.

Guarda, nessuno qua vuole flammare. O meglio *io* non voglio flammare. E per flammare bisogna essere (almeno) in 2.
Ti faccio un breve riassunto della vicenda vista da fuori (e senza prendere parte):

Tu: Ho provato ad eseguire questo esempio e ho ottenuto questo stacktrace (citazione: mi sono bloccata, probabilmente per qualche mancanza mia conoscitiva di base)  
Ric: Quel tutorial da per scontata una certa esperienza su Python e sul tuo ambiente [il path che specifichi non va bene con Windows]; ovvero, Python effettivamente ti dice quale e' il problema -- file non valido --, ma per vederlo devi sapere leggere la stacktrace; quello che non ti dice e' perche' quel path non e' valido e l'unico modo per capirlo e' conoscere un pochetto windows. In tutta onesta' io per esempio non ho la minima idea di come siano i path sul credo ormai defunto RiscOS e non avrei la piu' pallida idea -- senza googolare -- di quale possa essere un path valido

Un mio commento? Forse Ric e' stato un pelo brusco, ma niente di che (e niente in confronto a quello che faccio io). Tu in compenso hai risposto con umilta' in modo ineccepibile:

Tu:
> Programmare in Python -> ok, anche se non livello ottimo.
> Avere a che fare col SO -> not ok, in particolare i path vari e compagnia bella, non sono per niente esperta.

Ric: Ti *spiega* una metodologia su come risolvere (nel futuro) da sola questo tipo di errori.

Fino a questo punto non c'era nulla di flammoso. Tu rispondi ancora in modo "tranquillo", anche se cominci con stralci del famoso CV. Tua scelta. Ora io stavo per rispondere a questo tuo messaggio, verosimilmente in maniera pungente, per un paio di cose che hai scritto e che commentero' poi a parte. Solo che... qualcuno ha risposto in maniera ancora piu' pungente. E da li e' tutto degenerato.

Come dicevo... non si flamma da soli. ;)


Tornando alla questione che hai sollevato:

> Pensavo solamente che PY per il Web (Flask, poi nello specifico - premetto che sono esperta in PHP) fosse maggiormente "intelligente", ma è evidente che non sia così wink

Non e' evidente che sia come dici. In primo luogo in tutto questo flask e' coinvolto solo in maniera trasversale. La causa del problema e' che tu provi ad aprire un file (che poi e' pure un db file di sqlite, ma questo e' ancora trasversale) in una posizione non valida. Questo non funziona nella maggior parte dei linguaggi a me noti: *deve* darti un errore, perche' non puo' darti quello che chiedi. Mi aspetto che perfino Perl per una roba del genere ti dia una qualche forma di errore invece che fallire silenziosamente come fa di solito.

Il problema e' che frasi del genere, come dire, incoraggiano il flame. Fermo restando che i flame poi non si fanno da soli.

Citazione
No, in quanto a SO in sé il concetto di PATH mi è sempre stato abbastanza ostico, non ho avuto abbastanza da sbatterci la testa (a parte litigi con il prompt dei comandi, files in lettura/scrittura, e cose piuttosto banali) - ma è una cosa che ho detto fin dall'inizio, e se volessi sbatterci la testa lo farei per bene e con oculato studio.

De gustibus. Capisco che sia qualcosa che non ti piace, non capisco come hai fatto a non sbatterci la testa prima -- nel senso che nella maggior parte dei progetti su cui ho lavorato in un modo o nell'altro qualche tipo di file era coinvolto --; in realta' non c'e' nulla di davvero complicato. O meglio... tutta la pappardella e' complicata, ma il minimo che serve nel 95% dei casi e' piuttosto semplice. Se ti scappano due ore libere dacci un occhio, e' un buon consiglio.


Citazione
Il fatto che molti esempi siano soprattutto in Linux mi fa pensare: ma il tempo di costruire una guida altrettanto semplice per Win, no?
Cos'era, troppo poco figo? Il 91% dei progetti Desktop è Windows-based, maledizione, NON è un numero ignorabile (scusate il maiuscolo ma ce voleva).

Credo che complessivamente la percentuale di sviluppo Python su windows sia piuttosto trascurabile. Specie per cose web-based, dove alla fine della storia il deploy finira' su un host unix nella stragrande maggioranza dei casi. E in effetti, perfino per il desktop non so se le percentuali che dai siano corrette (in particolare, Python e' piuttosto usato su Linux e affini anche per le app desktop -- non ho idea di cosa accada sotto Windows).

Ma insomma... se gli sviluppatori Windows sono pochi, o non usano Flask, o non hanno voglia di scrivere tutorial o chennesoio... e', chennesoio...

Possibile anche che la difficolta' di convertire "a mente" un tutorial per Linux sia relativamente bassa e non valga lo sforzo di "duplicare" la documentazione. Ora se davvero e' solo questione di rendersi conto che /tmp sotto Windows si chiama in un altro modo (o che puoi piazzare il file del db dove ti pare a patto che sia un percorso valido), *forse* effettivamente non e' un problema per la maggior parte delle persone.

Dopo di che... sempre divagando, sono in giro sul web da parecchi parecchi anni. In generale quando si ha un errore banale (perdonami, ma questo e' un errore banale) *e* si sciorina il CV di solito *finsce* male. E sinceramente sta volta e' anche andata "bene"; in occasioni simili, e in altri lidi, probabilmente sarebbe finita molto peggio. Oh, peggio si fa per dire... al piu' si scrive roba che qualcuno non vuole leggere, si viene presi un po' in giro e poi finisce li. Il problema e' che ogni volta che ci si definisce "esperti" in qualcosa... diciamo che essere esperti e' piu' soggettivo che intersoggettivo.

Un riko che non lavora per Google.
... e che sinceramente non ama le flamewar che non ha scatenato da se medesimo. ;)

-- moccatela --

Offline juliux

  • python unicellularis
  • *
  • Post: 28
  • Punti reputazione: 0
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #12 il: Febbraio 23, 2015, 18:56 »
Allora, faccio un ultimo intervento, poi mi fermo perchè non voglio inquinare ulteriormente il topic  :angel:.

juliux, questo era innecessariamente brusco.

Solo che... qualcuno ha risposto in maniera ancora piu' pungente. E da li e' tutto degenerato.

Il mio primo post voleva essere scherzoso, non certo pungente e provocatorio. Ho messo apposta anche uno smile, ma questo è uno dei classici esempi in cui si evidenziano i limiti della comunicazione scritta, rispetto a quella verbale (su un forum è assai difficile evidenziare caratteristiche quali espressioni del viso o tono della voce...). Il fatto che ben tre persone non abbiano percepito l'ironia, sta a significare che l'errore l'abbia commesso io, non chi leggeva. Per tale motivo, mi scuso pubblicamente con AliceForgotten e con tutto il resto dell'utenza.

Quello che volevo dire... Ho linkato un qualcosa che evidenzia come la sintassi di questo linguaggio debba essere estremamente chiara e non preveda 'magie'. In particolare, mi riferivo alle due righe che cito qui:

Citazione
Explicit is better than implicit.
Simple is better than complex.

Analogamente, credo che nell'imparare una nuova tecnologia sia necessario partire dalle basi, indipendentemente dalle conoscenze pregresse (da qui la frase "Potresti essere super-esperta pure di ingeneria aero-spaziale"). Lo Zen di Python secondo me, è un qualcosa di simbolico, ma è pur sempre qualcosa da conoscere (e io lo adoro veramente mattina e sera come una sacra scrittura, che c'è di male?).

Offline RicPol

  • python sapiens sapiens
  • ******
  • Post: 2.876
  • Punti reputazione: 9
    • Mostra profilo
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #13 il: Febbraio 23, 2015, 21:53 »
Citazione
in C, come in tanti altri linguaggi ma soprattutto in C, se un path non esiste lo crea in automatico se in scrittura

eh, ma lo sapevo che a questo punto sarebbe arrivato riko ;-)
riko, va bene, +1, ma guarda, ho come il sospetto che qui si stava volando un po' più basso.


Comunque, aggiungiamo ancora qualcosa sui pathname (oh... proprio un bignami semplificatissimo, eh?), hai visto mai che poi ci si lamenta dell'incompletezza delle spiegazioni.

In linux il file system si dirama a partire da un'unica origine detta "root" ed espressa col simbolo "/".
In windows non esiste il concetto di root unica. Ogni dispositivo fisico ha un suo file system separato, che origina da una sua propria root (ossia la lettera che viene assegnata al dispositivo dal sistema operativo). In linux, d'altra parte, i dispositivi fisici possono essere invece "montati" dinamicamente in punti qualsiasi del file system.
Anche in windows esiste il simbolo "/" per dire "root", ma vuole solo dire "la root del dispositivo fisico corrente".
Di conseguenza, quando in una shell (**) scrivi cd /, in linux vuoi dire "vai alla root" (e sai sempre dove vai). In windows invece vuoi dire "vai alla root del dispositivo corrente", e in generale non puoi sapere a priori dove ti porterà un cd / (dipende da qual è in quel momento il dispositivo corrente; puoi fare la prova).

In tutte le distribuzioni linux, per convenzione è fornita una directory /tmp (ossia: una directory che si chiama "tmp" e sta subito sotto la root). Questa è una directory per file temporanei: periodicamente il sistema operativo si incarica di ripulirla. Se metti un file in /tmp sai che puoi dimenticarti di eliminarlo, ci pensa il s.o. per te.
Anche in windows naturalmente esiste il concetto di "directory per i file temporanei". A onor del vero ce ne sono diverse: esiste c:/windows/temp come ultima risorsa, ma nei sistemi windows moderni le applicazioni "normali" sono incoraggiate a usare la tempdir (come viene amichevolmente chiamata) dell'utente loggato. Ogni utente ne ha una diversa, quindi. Puoi vedere la tua scrivendo in una shell echo %tmp%. Si suppone che le applicazioni windows che desiderano scrivere nella tempdir, devono prima risolvere (o "esplodere" come si dice amichevolmente) la variabile %tmp% e poi usare la directory indicata.
In python (ovvero: se stai scrivendo un'applicazione python che vuole usare la tempdir di windows nel modo "giusto" secondo le raccomandazioni) questo si ottiene semplicemente passando da os.environ:
[codice]
import os, os.path
tmp = os.environ['tmp']
# e poi, per esempio....
open(os.path.join(tmp, 'temporary_file.txt'))
# etc etc
[/codice]
(nota che questo codice funziona benissimo anche per linux, dove semplicemente os.environ['tmp'] ritorna banalmente la famosa /tmp).

Naturalmente, in tutto questo, ormai dovrebbe essere chiaro (ma esplicitiamo, hai visto mai) che in windows /tmp (ovvero, ma - attenzione! - non sempre: c:/tmp) banalmente non esiste. Il s.o. non la mette a disposizione di per sé... magari qualche utente burlone l'ha creata lui, e quindi te la trovi. Oppure, più spesso: qualche applicazione mal scritta l'ha creata in precedenza, e quindi te la trovi. Perché dico "applicazione mal scritta"? Perché non basta creare una directory e chiamarla tmp perché diventi una "directory per file temporanei": anche se esiste, windows non la "conosce", e non la gestisce. Semplicemente, i file messi lì dentro non verranno mai ripuliti dal sistema operativo.



E questo più o meno conclude il bignami sulle tempdir.
Ora, passando al caso specifico, quando uno copia passo-passo un tutorial facendo attenzione a quello che scrive, nel momento in cui si trova un /tmp/qualcosa, se appena ha una superficiale conoscenza di windows sgama subito il problema. Quell'espressione vuole chiaramente dire "sbatti questo file nella tempdir, tanto questo è solo un tutorial e i file creati qui sono spazzatura"..., e per dire "sbattilo nella tempdir" utilizza un pattern tipico di linux (perché il pattern di linux è più corto e più chiaro da scrivere; oppure chissà, perché sta scrivendo il tutorial su una macchina linux... capita). Ma tu apri l'occhio, ti ricordi che sei invece su una macchina windows, sai bene che la tempdir in windows è da tutt'altra parte, e quindi hai la scelta:
- o "traduci" al volo sostituendo con la tempdir di windows (elegante, ma lunghetto)
- o lasci perdere e sbatti il tuo file in una directory qualsiasi (magari la directory corrente... se sai qual è la directory corrente in quel momento, beninteso!) e poi lo cancelli a mano quando non ti serve più.

Ecco, più o meno questo è quanto. Poi viene tutto quello che ha scritto riko su fopen e compagnia... a cui aggiungo solo, ma certo, anche su windows ti trovi errno settato su ENOENT, ci mancherebbe. Sinceramente non capisco che cosa indendesse l'OP con " in C, come in tanti altri linguaggi ma soprattutto in C, se un path non esiste lo crea in automatico se in scrittura"... forse pensava a mkdir, ma se ben ricordo neanche mkdir fa una cosa del genere (disclaimer: io e il c abitiamo in universi paralleli: ogni tanto un buco nero mi porta da quelle parti ma dura solo un istante). E quanto agli "altri linguaggi", boh... sicuramente ci sono un sacco di funzioni ovunque che implementano questo... in python per dire, os.makedirs... ma l'idea specifica di implementare "open" in questo modo non saprei proprio dove l'ho vista... mah.




E infine, come nota a margine, mi colpisce veramente molto anche questo:
Citazione
Il fatto che molti esempi siano soprattutto in Linux mi fa pensare: ma il tempo di costruire una guida altrettanto semplice per Win, no?
Cos'era, troppo poco figo? Il 91% dei progetti Desktop è Windows-based, maledizione, NON è un numero ignorabile (scusate il maiuscolo ma ce voleva).
Te lo ha già fatto notare riko, ma insomma, è che proprio non resisto a dirtelo anche io.

Ora, a parte che è abbastanza noto che la community python è da sempre più linux che windows, quindi non vedo dove sta lo stupore. D'altra parte, se ci pensi, non trovi molti esempi e tutorial C# scritti in ambiente e con mentalità linux.
Ma poi, nello specifico, qui non stiamo parlando di desktop ma di Flask, che fa parte di tutta quella categoria di software che di solito non girano sulla workstation, ma sui server. E queste macchine di solito sono linux, come è ben noto.
Sono osservazioni rivelatorie come queste che stridono pesantemente con i vari "lunga esperienza", "c e una dozzina di linguaggi", e via curricolando. Ora, come dice riko, finché resti su un forum, mah sai, poco male: qualcuno sogghigna un po', tu ti impermalosisci, alla fine magari ci si scusa a vicenda, e fine della giornata. Basta non farsi scappare una cosa del genere a un colloquio di lavoro, suppongo.




________
(**) hai visto mai che non è chiaro: "una shell" qui non significa "una shell python", ma proprio "una shell"... In linux sarebbe "bash" per dire... In windows è "cmd.exe" o "powershell.exe"... quella roba lì. Ci siamo capiti.
« Ultima modifica: Febbraio 23, 2015, 22:02 da RicPol »

Offline riko

  • python deus
  • *
  • moderatore
  • Post: 7.453
  • Punti reputazione: 12
    • Mostra profilo
    • RiK0 Tech Temple
Re: Flask - Esempio "Flaskr" e connessione al Database con SQLite3
« Risposta #14 il: Febbraio 23, 2015, 22:49 »
riko, va bene, +1, ma guarda, ho come il sospetto che qui si stava volando un po' più basso.

Io non posso che rifarmi a quello che OP dice.

Citazione
In tutte le distribuzioni linux, per convenzione è fornita una directory /tmp (ossia: una directory che si chiama "tmp" e sta subito sotto la root).

Si. In generale e' una convenzione su Unix ed e' parte dello standard LFHS per Linux.

Citazione
Questa è una directory per file temporanei: periodicamente il sistema operativo si incarica di ripulirla. Se metti un file in /tmp sai che puoi dimenticarti di eliminarlo, ci pensa il s.o. per te.

Questo in effetti non e' vero. A seconda dei sistemi potrebbe essere pulita al boot (che nel caso di un sistema Linux potrebbe volere dire ogni qualche mese o anche ogni qualche anno), pulita giornalmente o chissa' cosa. Il comportamento in essenza dipende dalla distribuzione.

Se vuoi davvero un file che puoi dimenticarti di eliminare, in Python ci sono apposite funzioni (nel senso che Python sa che lo elimina, per esempio quando viene chiuso).

Ovviamente si, non mi preoccuperei di /tmp che si satura. In questo senso chissene frega... in generale qualcuno lo pulira' per te (basta avere idea di chi e di quando) e se anche non ci fosse due botte con find risolvono il problema.

Dopo di che, scusate, non focalizziamoci sulle tempdir. Non c'e' nessun motivo pratico per cui si debba usare una tempdir per questo (anzi, verosimilmente non si vuole farlo). Cioe' un conto e' il fatto che per un esempio di un tutorial su internet abbia senso: ci scrivono tutti (in genere) ed e' roba che a uno non interessa accumulare. Ma se OP si mette il file nella home funziona bene uguale (a patto che sappia il path della home, ben inteso).


Citazione
- o lasci perdere e sbatti il tuo file in una directory qualsiasi (magari la directory corrente... se sai qual è la directory corrente in quel momento, beninteso!) e poi lo cancelli a mano quando non ti serve più.

+1


Citazione
Poi viene tutto quello che ha scritto riko su fopen e compagnia... a cui aggiungo solo, ma certo, anche su windows ti trovi errno settato su ENOENT, ci mancherebbe.

Non e' affatto garantito. Cioe', se mi dici che e' cosi' e' cosi', ma non e' che debba essere cosi'.
Lo standard non dice nulla in proposito e la maggior parte dei nomi degli errori non sono particolarmente standardizzati.
Per esempio su un sistema Linux su cui ho accesso ti da ENOENT anche nel caso in cui tu fai /foo/afile/newfile, mentre la stessa cosa su OS X ti da ENOTDIR.
In particolare solo ERANGE ed EDOM sono definiti (pare di ricordare che ce ne fosse un terzo, a memoria... ma non mi viene).

Ah, ecco, ricordavo bene: EILSEQ; sono andato a pescare da SUS.

Quindi sarebbe assolutamente lecito che un'implementazione C (magari, ma non necessariamente per Windows) usasse qualcosa di diverso. Perfino un'implementazione Posix compliant potrebbe fare qualcosa di diverso: ENOENT dice solo "No such file or directory." Potrebbe tranquillamente usare qualcosa di diverso, a mio avviso. Ma non voglio fare il posix lawyer. Sicuro rinunciando a Posix potrebbe tirarti un EANTANI e nessuno si potrebbe lamentare. O meglio... chi deve debuggare si lamenterebbe eccome, ma tant'e'.

Citazione
Sinceramente non capisco che cosa indendesse l'OP con " in C, come in tanti altri linguaggi ma soprattutto in C, se un path non esiste lo crea in automatico se in scrittura"...

Secondo me ad OP non e' chiaro che il problema non era nel file, ma nella mancanza della directory. Semmai, si riferiva al fatto che se fai

/validdir/foo

foo te lo crea (ammesso che ci siano i permessi). Ma ovviamente qui il problema era diverso.

Citazione
forse pensava a mkdir, ma se ben ricordo neanche mkdir fa una cosa del genere (disclaimer: io e il c abitiamo in universi paralleli: ogni tanto un buco nero mi porta da quelle parti ma dura solo un istante).

Beh, sembra che te la cavi piuttosto bene per stare in universi paralleli... e no, mkdir non lo fa da sola. L'utility cmd line lo fa con l'opzione p. mkdir(2) non lo fa.
Il motivo e' che in generale non e' *affatto* banale capire cosa fare quando ti manca un pezzo di path. A volte e' utile creare tutto quello che manca, ma nella maggior parte dei casi e' rischioso che il sistema decida per te. Meglio un errore. Se ti serve makedirs (a la python) sono poche righe di C.