Questa guida descrive l’intero processo per autenticarsi su Google Drive API, leggere e scrivere file JSON, e ottimizzare la gestione dell’accesso utilizzando Python. Si partirà dalla configurazione su Google Cloud, passando per la creazione delle credenziali, fino all’installazione delle librerie necessarie e alla gestione del flusso di autenticazione.
Per utilizzare le API di Google Drive, bisogna configurare un progetto su Google Cloud Console. Il primo passo è accedere alla piattaforma andando su Google Cloud Console. Se non si è già registrati, sarà necessario creare un account Google Cloud.
Una volta effettuato l’accesso, si deve creare un nuovo progetto. Nella barra superiore della console, c’è un menu a tendina per la selezione del progetto. Cliccando su di esso, si apre una finestra con l’opzione per creare un nuovo progetto. Dopo aver scelto un nome per il progetto e confermato la creazione, sarà possibile accedere alle impostazioni del progetto stesso.
Abilitazione dell’API di Google Drive
Dopo aver creato il progetto, è necessario abilitare l’API di Google Drive. Nel menu laterale della Google Cloud Console, cliccate su Soluzioni e poi su Tutti i Prodotti. Nella scermata successiva troverete la sezione "API e servizi". Entrando in questa sezione, bisogna cercare Google Drive API nella barra di ricerca e selezionarla. Verrà visualizzata una pagina con il pulsante "Abilita", che deve essere premuto per attivare l’API nel progetto.
Creazione delle Credenziali OAuth2
Per autenticarsi su Google Drive tramite Python, servono le credenziali OAuth2. Nella stessa sezione "API e servizi", c’è un menu chiamato "Credenziali". Da qui, si può creare un nuovo set di credenziali cliccando su "Crea credenziali" e selezionando "ID client OAuth".
Durante la configurazione, Google chiede di impostare la schermata di consenso OAuth. Questa schermata è necessaria per autorizzare l’accesso all’API. Se l’applicazione è destinata solo al proprio account, si può scegliere l’opzione "Interno", altrimenti è necessario selezionare "Esterno", il che potrebbe richiedere una revisione da parte di Google prima che l’app sia accessibile ad altri utenti.
Quando viene chiesto il tipo di applicazione, bisogna selezionare "Applicazione desktop", perché Python non viene eseguito su un server remoto ma in locale. Configurate anche la voce URI di reindirizzamento autorizzati dove gli utenti verranno reindirizzati a questo percorso dopo aver eseguito l'autenticazione con Google. Al percorso verrà aggiunto il codice di autorizzazione per l'accesso. Deve avere un protocollo. Non può contenere frammenti di URL, percorsi relativi o caratteri jolly. Non può essere un indirizzo IP pubblico. Dovremmo quindi anche predisporre un DNS che punti alla porta su cui faremo girare il server di autenticazione. Per il momento, visto che il tutorial andrà provato in locale, impostiamo le voci come da immagine.
Dopo aver completato la configurazione, Google genererà un client ID e un client secret, e fornirà un file JSON da scaricare. Questo file contiene le credenziali necessarie per l’autenticazione e deve essere conservato in un percorso sicuro sul computer.
Installazione delle Librerie Necessarie
Prima di poter interagire con Google Drive in Python, è necessario installare le librerie appropriate. Il pacchetto principale è google-auth, che permette di gestire l’autenticazione OAuth2. È necessario anche google-auth-oauthlib per il flusso di autenticazione e google-auth-httplib2 per la gestione delle richieste HTTP. Infine, la libreria google-api-python-client fornisce le API per accedere ai servizi di Google.
L’installazione avviene con il comando:
pip install google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client
Una volta completata l’installazione, si può procedere con l’implementazione dell’autenticazione e della gestione dei file su Google Drive.
Autenticazione su Google Drive con OAuth2
Dopo aver configurato il progetto su Google Cloud e installato le librerie necessarie, bisogna implementare un sistema di autenticazione che permetta di accedere a Google Drive. Il file JSON scaricato in precedenza contiene tutte le informazioni necessarie per autenticarsi tramite OAuth2.
Per evitare di dover effettuare l’autenticazione ogni volta, è opportuno salvare il token in locale. Questo permette di riutilizzarlo finché non scade, evitando di avviare il server locale di autenticazione a ogni esecuzione.
Gestione dell’Autenticazione con un Singleton
Per garantire che l’autenticazione venga eseguita una sola volta e che il token venga riutilizzato, si può implementare una classe Singleton. Il Singleton assicura che venga creata una sola istanza della classe in tutto il programma.
Questo è il codice della classe che gestisce l’autenticazione:
import os
import json
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from django.conf import settings
from google.oauth2.credentials import Credentials
class GoogleDriveAuth:
_instance = None
_creds = None
def __new__(cls, *args, **kwargs):
# Implementa il pattern Singleton: crea una sola istanza della classe
if cls._instance is None:
cls._instance = super(GoogleDriveAuth, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
if not self._creds:
self._creds = self.authenticate()
@staticmethod
def authenticate():
"""
Autenticazione con Google Drive e restituisce le credenziali.
Se le credenziali sono scadute, le rinnova, altrimenti le carica.
"""
try:
# Percorso del file delle credenziali di Google Drive
base_dir = settings.BASE_DIR
credentials_json = os.path.join(base_dir, 'credentials', 'client_secret_google_drive.json')
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly', 'https://www.googleapis.com/auth/drive.file']
# Verifica se ci sono credenziali già salvate nella sessione
creds = None
if 'google_token' in globals(): # sostituisci con il tuo meccanismo di gestione del token
creds = Credentials.from_authorized_user_info(globals()['google_token'])
# Se non ci sono credenziali o sono scadute, avvia il flusso di autenticazione
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(credentials_json, SCOPES)
creds = flow.run_local_server(port=8080) # Usa una porta libera
globals()['google_token'] = json.loads(creds.to_json()) # Salva il token in globale o dove necessario
return creds
except Exception as e:
raise Exception(f"Errore durante l'autenticazione su Google Drive: {e}")
def get_creds(self):
"""
Restituisce le credenziali di Google Drive.
"""
return self._creds
Questa classe esegue il controllo se esiste già un token.json salvato. Se il file è presente, il token viene caricato e utilizzato per autenticarsi. Se il token è scaduto, viene aggiornato automaticamente. Nel caso in cui non esista alcun token, viene avviata l’autenticazione con run_local_server, che avvia un server locale e apre il browser per effettuare il login con Google.
Leggere i files all'interno di una cartella di Google Drive
Google Drive non ha una struttura di directory come un normale file system, ma utilizza identificatori univoci per ogni file e cartella. Per accedere a una cartella specifica, dobbiamo conoscere il suo id
. Nel nostro caso, abbiamo creato un file JSON in cui mappiamo il nome delle cartelle ai loro rispettivi id
. Questo ci permette di recuperare rapidamente il valore corretto e utilizzarlo per filtrare i file presenti in una cartella.
Per leggere i file JSON presenti in una cartella su Google Drive, dobbiamo:
- Autenticare l'utente con le credenziali di Google Drive
- Ottenere l'
id
della cartella in cui sono contenuti i file - Eseguire una query per recuperare tutti i file JSON nella cartella
- Scaricare e leggere il contenuto del file
Ecco un esempio di codice per leggere i file JSON da una cartella:
from googleapiclient.discovery import build
import json
from googleapiclient.http import MediaIoBaseDownload
import io
class GoogleDriveManager:
def __init__(self, creds):
self.service = build('drive', 'v3', credentials=creds)
def get_folder_id(self, folder_name):
"""
Recupera l'ID della cartella dal file JSON contenente la mappatura nome → ID.
"""
try:
with open('google_drive_folders.json', 'r') as f:
folder_data = json.load(f)
return next((item['id'] for item in folder_data if item['name'] == folder_name), None)
except Exception as e:
raise Exception(f"Errore nel recupero dell'ID cartella: {e}")
def list_json_files(self, folder_id):
"""
Restituisce un elenco di file JSON all'interno di una cartella specifica.
"""
try:
results = self.service.files().list(
q=f"'{folder_id}' in parents and mimeType = 'application/json'",
pageSize=100,
fields="files(id, name)"
).execute()
return results.get('files', [])
except Exception as e:
raise Exception(f"Errore durante il recupero dei file JSON: {e}")
def read_json_file(self, file_id):
"""
Scarica e legge il contenuto di un file JSON su Google Drive.
"""
try:
request = self.service.files().get_media(fileId=file_id)
file_content = io.BytesIO()
downloader = MediaIoBaseDownload(file_content, request)
done = False
while not done:
_, done = downloader.next_chunk()
file_content.seek(0)
return json.load(file_content)
except Exception as e:
raise Exception(f"Errore durante la lettura del file JSON: {e}")
# ESEMPIO D'USO
auth = GoogleDriveAuth()
creds = auth.get_creds()
drive_manager = GoogleDriveManager(creds)
folder_name = "spacy"
folder_id = drive_manager.get_folder_id(folder_name)
if folder_id:
json_files = drive_manager.list_json_files(folder_id)
for file in json_files:
file_content = drive_manager.read_json_file(file['id'])
print(f"Contenuto di {file['name']}: {file_content}")
Questo codice:
- Ottiene l'
id
della cartella corrispondente al nome fornito. - Recupera la lista di file JSON all'interno della cartella.
- Scarica e legge il contenuto di ciascun file JSON.
Scrivere un nuovo file JSON su Google Drive
Per scrivere un nuovo file JSON dentro una cartella su Google Drive, dobbiamo:
- Verificare se esiste già un file per il mese corrente, per aggiornarlo.
- Creare un nuovo file se non ne esiste uno attuale.
Ecco un esempio di codice per scrivere su Google Drive:
from googleapiclient.http import MediaFileUpload
import datetime
import os
class GoogleDriveWriter:
def __init__(self, creds):
self.service = build('drive', 'v3', credentials=creds)
def upload_json(self, folder_id, data, filename=None):
"""
Carica un nuovo file JSON o aggiorna quello esistente nel mese corrente.
"""
try:
# Controlliamo se esiste un file JSON del mese corrente nella cartella
current_month = datetime.datetime.now().month
results = self.service.files().list(
q=f"'{folder_id}' in parents and mimeType='application/json'",
fields="files(id, name, modifiedTime)"
).execute()
items = results.get('files', [])
json_file_id = None
for item in items:
modified_time = datetime.datetime.strptime(item['modifiedTime'], '%Y-%m-%dT%H:%M:%S.%fZ')
if modified_time.month == current_month:
json_file_id = item['id']
break
# Percorso temporaneo per salvare il file JSON
temp_path = '/tmp/temp_file.json'
with open(temp_path, 'w') as f:
json.dump(data, f)
media = MediaFileUpload(temp_path, mimetype='application/json', resumable=True)
if json_file_id:
# Se il file esiste già, aggiorniamolo
self.service.files().update(fileId=json_file_id, media_body=media).execute()
print(f"Aggiornato il file esistente con ID: {json_file_id}")
else:
# Creiamo un nuovo file
new_filename = filename or f"{int(datetime.datetime.timestamp(datetime.datetime.now()))}.json"
file_metadata = {'name': new_filename, 'mimeType': 'application/json', 'parents': [folder_id]}
self.service.files().create(body=file_metadata, media_body=media).execute()
print(f"Creato nuovo file JSON: {new_filename}")
except Exception as e:
raise Exception(f"Errore durante il caricamento del file JSON: {e}")
# ESEMPIO D'USO
auth = GoogleDriveAuth()
creds = auth.get_creds()
drive_writer = GoogleDriveWriter(creds)
folder_name = "spacy"
folder_id = drive_manager.get_folder_id(folder_name)
data_to_upload = [{"id": 1, "name": "Esempio"}, {"id": 2, "name": "Dati"}]
if folder_id:
drive_writer.upload_json(folder_id, data_to_upload)
Conclusione
Abbiamo visto come autenticarsi a Google Drive con le API, utilizzare il pattern Singleton per gestire le credenziali e come interagire con i file JSON su Google Drive. Ora possiamo:
- Leggere i file JSON all'interno di una cartella, sfruttando l'ID della cartella.
- Scrivere e aggiornare i file JSON in base al mese corrente, evitando di creare file duplicati.
Questo metodo garantisce un'ottima gestione dei file, evitando sovrascritture inutili e ottimizzando il recupero e la memorizzazione dei dati.