Semplifica la condivisione dei file

Semplifica condivisione file

Esempio di codifica per lavorare con le cartelle condivise di Google Drive in progetti di collaborazione

Di recente si è ripresentato un problema di condivisione dei dati, e ho pensato che questo sarebbe stato un buon momento per progettare un metodo per lavorare con le cartelle condivise. Lavoro come professionista GIScience indipendente e collaboro frequentemente con diverse organizzazioni contemporaneamente. Nei miei progetti ho notato che ogni organizzazione ha il suo approccio unico al lavoro con i dati, plasmato dalla sua cultura e dalle sue etiche lavorative distinte, il che porta a una vasta gamma di metodologie. Per fortuna, ci sono alcune pratiche che hanno in comune, e una di queste è il lavoro con un sistema di gestione dei dati basato su cloud, spesso Google, ma potrebbe anche essere One-Drive (di Microsoft) o Dropbox.

In questo post, spiegherò come utilizzare Python con le cartelle condivise nell’Ecosistema Google.

Foto di Annie Spratt su Unsplash

Caso di utilizzo

Come gestire i file su una macchina locale è molto individuale e (sperabilmente) standardizzato, o almeno ha una certa standardizzazione, quando si lavora in un’organizzazione. La condivisione di file tra sistemi può essere complicata, ma lavorare con cartelle condivise è un’opzione quando non si ha accesso diretto a una cartella di produzione e l’organizzazione può condividere con te una cartella di lavoro specificamente designata per lo scambio di file. In questo esempio, un’organizzazione ha concesso l’accesso a una cartella chiamata DATA nel loro repository di Google Drive ed è stato concordato che possiamo utilizzare questa cartella per scambiare file.

Gestione dei file locali

Per spiegare velocemente, per le persone non familiari con la condivisione di file di Google Drive, il processo inizia ricevendo una email che ti invita a contribuire a una cartella specifica; vedi l’invito (a sinistra) qui sotto. Nell’invito c’è un pulsante che aprirà un browser web con l’interfaccia di Google Drive (a destra) associata all’email di Google del destinatario dell’invito.

Figura 1: Creazione di una cartella condivisa (immagine dell'autore)

Ci sono alcune informazioni importanti nascoste nell’interfaccia e capirle in anticipo aiuterà con il resto del processo.

  • Nell’URL (in alto dello schermo) c’è un ID mascherato, questo è l’ID che Google utilizza per tracciare tutte le operazioni su questa cartella e che recupereremo nel codice Python più avanti in questo post.
  • Poi dice: “Condiviso con me” e il nome della cartella condivisa; anche questo è importante perché quando montiamo Google Drive sul notebook CoLab, vedremo che questa categoria non è disponibile.
  • E infine, vediamo i file e le cartelle sotto Data; questo significa che possiamo accedere alle informazioni di cui abbiamo bisogno e aggiungere nuovi file alla cartella. Tuttavia, potrebbe esserci un problema con le impostazioni di sicurezza della cartella, quindi un buon test in questa fase è creare un piccolo file di testo e trascinarlo nella cartella “ExternalData” per verificare di avere un accesso completo.

Per rendere accessibile la cartella “Condiviso con me”, è necessario collegare questa cartella al drive locale/personale. Possiamo farlo creando un collegamento, ma questo è un passaggio manuale e sarà diverso per tutti. Per accedere a una cartella o un file condiviso con te su Google Colab, devi:

  1. Andare a “Condiviso con me” in Google Drive.
  2. Selezionare la cartella o il file a cui desideri accedere.
  3. Fare clic destro su di esso e scegliere “Aggiungi collegamento al drive”, apparirà una finestra popup “Seleziona MyDrive”, quindi fare clic su “Aggiungi collegamento”.
  4. Posizionare il collegamento in una posizione sul tuo drive che puoi ritrovare facilmente; nell’impostazione che utilizzo, la posizione per i collegamenti è “__Shared”, assicurando che la cartella con i collegamenti sia in cima alla lista delle cartelle sotto “MyDrive” e quindi una sottodirectory per l’organizzazione.
  5. Rinominare il collegamento con un nome significativo; in questo esempio uso “DataDevelopement”. La posizione e le convenzioni di denominazione dei file sono molto personali e non importa al programma dove sono archiviati o come sono chiamati, ma avere una certa struttura può evitare alcuni mal di testa in seguito.
Figura 2: Creazione di un collegamento (immagine dell'autore)

Con il file system locale organizzato e il Google Drive personale configurato, possiamo provare a lavorare con questa cartella condivisa in un notebook Python e automatizzare la condivisione dei file nel progetto.

Installazione

Questo progetto si basa su un notebook Google Colab, o “Collaboratory”, che condividerò alla fine di questo articolo. Il vantaggio di utilizzare questo ambiente è che ti consente di scrivere ed eseguire Python nel tuo browser, con

  • Nessuna configurazione richiesta
  • Accesso gratuito alle GPU
  • Facilità di condivisione

Questi sono punti molto importanti quando si lavora con organizzazioni che hanno le loro procedure interne perché, come collaboratore esterno, spesso non si ha accesso diretto alla base di codice (e ciò può avere molte ragioni diverse, dalle preoccupazioni sulla sicurezza ai vincoli di gestione del progetto). Il notebook Colab fa parte dell’ecosistema di Google e (come vantaggio aggiuntivo) crea un ambiente di esecuzione con l’opzione di montare i drive personali di Google (per la condivisione dei file).

Importazione di moduli e pacchetti

In questo esempio, vengono caricati solo i pacchetti necessari per l’esecuzione del notebook e abbiamo bisogno di alcune librerie specifiche per lavorare con il drive condiviso.

Autorizzazione di Google

from oauth2client.client import GoogleCredentialsfrom google.colab import auth as google_authgoogle_auth.authenticate_user()from google.colab import drivedrive.mount('/content/gdrive')

Utilizzando oauth2client e le credenziali di Google semplificheremo il lavoro con i file. Ci sono alternative, come scaricare un file JSON con le credenziali, e ci saranno situazioni in cui lavorare con il file JSON sarà preferibile rispetto all’utilizzo delle credenziali di Google, ma essendo questo un progetto senza dati sensibili, la libreria oauth2client offre una protezione sufficiente.

pydrive

from pydrive.auth import GoogleAuthfrom pydrive.drive import GoogleDrivegauth = GoogleAuth()gauth.credentials = GoogleCredentials.get_application_default()drive = GoogleDrive(gauth)

pydrive è una libreria di supporto di google-api-python-client che semplifica molte delle operazioni comuni dell’API di Google Drive e una di queste funzionalità è la gestione delle risposte ottenute durante la query del sistema dei file di Google Drive. Google Drive memorizza tutti gli oggetti tramite ID e gli ID sono collegati da informazioni relazionali negli oggetti. È possibile accedere a queste informazioni tramite l’API (vedere il prossimo blocco di codice), ma la libreria di supporto svolge tutto il lavoro pesante per noi quando creiamo un’istanza di GoogleDriveFileList con i parametri di Files.list() come dizionario. Chiamando GetList() otterremo tutti i file che corrispondono alla tua query come una lista di GoogleDriveFile.

Client API di Google

# Client API di Google:from googleapiclient.discovery import build# Inizializza il client API di Google Drive drive_service = build('drive', 'v3')

Il Client API di Google è una libreria molto ampia e ha molte funzionalità, ma per questo progetto abbiamo bisogno solo di un modulo: build. Il modulo build costruisce un oggetto di risorsa per interagire con un’API e restituisce i metodi per interagire con il servizio. La libreria pydrive gestirà molto bene le funzioni di base, come la creazione, l’aggiornamento e l’eliminazione dei file, ma ci sono alcuni momenti (in questo progetto) in cui abbiamo bisogno di funzionalità più avanzate e avere accesso al “servizio” ci consente di estrarre informazioni non catturate dai metodi pydrive.

Questo conclude la configurazione del notebook. In questo esempio, non abbiamo bisogno di altre librerie oltre a quelle caricate per la gestione dei file e, con le librerie caricate, possiamo dare un’occhiata a cosa stanno facendo.

Gestione dei file nel notebook

Fino a questo punto, sono accadute alcune cose:

  • L’autorizzazione di Google è stata configurata,
  • Abbiamo creato l’accesso al drive (per l’accesso in lettura/scrittura) e
  • Il pacchetto Pydrive è disponibile per navigare nel drive

Speriamo che, quando segui il codice, vedrai l’immagine sulla destra, dopo aver aggiornato il pannello. Puoi vedere il collegamento nell’immagine come una cartella sotto “__Shared”, e non vediamo la sezione “Condiviso con me”, ma poiché abbiamo il collegamento, non abbiamo bisogno di vedere i file “Condivisi con me”.

Figura 3: Stati non montati vs. Stati montati dell'ambiente di esecuzione nell'interfaccia web di Google Colab (immagine dell'autore)

Google Drive funziona in modo diverso dalla gestione dei file nei sistemi operativi locali, la posizione fisica dei file non è importante perché gli oggetti sono gestiti tramite ID in un DataLake non strutturato e possiamo accedere ai file e alle cartelle tramite l’ID.

Purtroppo, mentre os.path (in Python) ha funzioni di navigazione per esplorare il file system, un metodo simile non esiste per Google Drive (o non ne sono a conoscenza). Tuttavia, possiamo utilizzare la libreria pydrive e navigare manualmente attraverso le cartelle nell’albero delle directory, e fortunatamente, sappiamo dove vogliamo andare a partire dal percorso della cartella. Quindi, non è necessario scorrere l’intera struttura, ma possiamo utilizzare i nomi delle cartelle del percorso dei dati per andare più in profondità nell’albero delle cartelle.

Quindi, facciamo un ciclo sulla piccola lista (in questo esempio, tre elementi) per trovare l’ID e utilizzare questo ID per passare al livello successivo. Si noti che il quarto livello è commentato; ci arriveremo nella seconda parte della sezione di gestione dei file di questo notebook.

# Test di gestione dei file:# In questo esempio ci sono tre livelli di cartelle:# /content/gdrive/MyDrive/__Shared/<your Project>/DataDevelopment# Aggiorna questi valori in base alla tua struttura:folderList1 = ["__Shared", tuo_Progetto, "DataDevelopment"] #, "ExternalData"]

Il ciclo, nel blocco di codice sottostante, parte dalla radice e quando trova un elemento nella lista, il ciclo utilizzerà l’ID dell’oggetto per passare al livello successivo nella lista, e se un elemento non viene trovato, il codice segnalerà che la cartella non è stata trovata e non cercherà altre cartelle più in profondità nella struttura. Il ciclo si conclude con l’ID della cartella Shortcut o segnala che la cartella non è stata trovata.

# Tentativo di copiare il file dummy creato:boo_foundFolder = FalsefileID = "root"level = 0# Visualizza tutte le cartelle e i file nel tuo Google Drive# Primo ciclo sulla lista:print("Struttura file e cartelle - verifica con ID")for folderName in folderList1:  print(f"Verifica: {folderName}")  if boo_foundFolder or fileID == "root": #primo avvio    boo_foundFolder = False    fileList = drive.ListFile({'q': f"'{fileID}' in parents and trashed=false"}).GetList()    for file in fileList:      # Test del nome:            if(file['title'] == folderName):        fileID = file['id']        boo_foundFolder = True        level += 1       # fine if    # fine for    if boo_foundFolder == False:      print(f"cartella non trovata")      break    # fine if      # fine if# fine forprint(f"Abbiamo trovato la cartella: {boo_foundFolder}")if boo_foundFolder:  print(fileID)  ShortCutID = fileIDelse:  ShortCutID = 0

In questo momento, abbiamo l’ID del file locale per la cartella di lavoro, ma prima di poter cercare file in questa posizione, dobbiamo abbinare questo ID locale con l’ID di destinazione della cartella condivisa. Per trovare queste informazioni, dobbiamo approfondire l’infrastruttura di Google, e per farlo, abbiamo bisogno di un aiutante: il drive_service. Abbiamo attivato l’assistente durante il caricamento del progetto e non abbiamo ricevuto un avviso, il che significa che abbiamo accesso al servizio utilizzando l’API e richiedendo informazioni tramite l’ID.

I dettagli di cui abbiamo bisogno sono meglio raccolti attraverso una semplice funzione, come la funzione findTargetID nel blocco di codice successivo. In questa funzione, il fileID è l’ID del collegamento rapido che abbiamo trovato facendo un ciclo sui nomi delle cartelle e chiamando drive_service.files().get e specificando i campi, otteniamo l’ID di destinazione della cartella (questo sarà lo stesso ID dell’URL dell’interfaccia web di Google Drive (vedi Figura 1).

def findTargetID(fileID, drive_service):  # L'ID del file condiviso da cui si desidera ottenere ShortcutDetails  file_id = fileID  try:      # Ottieni i dettagli del file      file = drive_service.files().get(fileId=file_id,                                       fields="id, shortcutDetails").execute()      # Verifica se il file è un collegamento rapido      if 'shortcutDetails' in file:          shortcut_details = file['shortcutDetails']          print("Dettagli collegamento rapido:")          print(f"ID di destinazione: {shortcut_details['targetId']}")          print(f"Tipo MIME di destinazione: {shortcut_details['targetMimeType']}")      else:          print("Il file non è un collegamento rapido.")      # fine if  except Exception as e:      print(f"Si è verificato un errore: {e}")  return shortcut_details['targetId']if boo_foundFolder:  targetID = findTargetID(fileID, drive_service)  print(targetID)else:  print("Cartella non trovata")# fine if

Con questo ID di destinazione, abbiamo accesso alla cartella condivisa effettiva sul server dei dati di Google e non stiamo più lavorando sulla cartella di collegamento.

Per riassumere, la ragione per cui abbiamo creato la cartella di collegamento era quella di poter vedere la cartella nella nostra lista di cartelle montate. La categoria “Condiviso con me” non è montata, ma i collegamenti lo sono. Quindi con questo nuovo ID possiamo cercare i file.

Cercare file

Ora abbiamo ciò di cui abbiamo bisogno, l’ID di destinazione della cartella condivisa con noi all’inizio del processo, e con quell’ID, tutte le operazioni normali sui file sono disponibili per noi.

Possiamo verificare di avere le autorizzazioni sufficienti sulla cartella condivisa creando prima un piccolo file di test nell’ambiente di esecuzione; la creazione di questo file conferma anche che abbiamo accesso all’ambiente di esecuzione perché apparirà nel pannello sinistro dell’interfaccia web del notebook CoLab quando il file viene creato correttamente.

# Crea un file di test:with open('example.txt', 'w') as f:  f.write('Questo è un file di esempio, per testare la condivisione dei file di CoLab')# questo file è ora presente nello spazio di esecuzione del notebook # (vedere la parte sinistra, sotto i file)

Ora l’idea è spostare questo file nella cartella “Condiviso con me” “Dati”, che abbiamo rinominato “DataSviluppo” nel collegamento, ma la funzione nella sezione precedente ha fornito l’ID di destinazione, e possiamo utilizzare ora questo ID per verificare se il file appena creato nell’ambiente di esecuzione è disponibile sull’unità condivisa.

if boo_foundFolder:  print("cartella trovata")  folderID = targetID  file_on_drive = False  file_id = 0    # controlla se il file è sull'unità:  fileList = drive.ListFile({'q': f"'{folderID}' in parents and trashed=false"}).GetList()  for file in fileList:    if(file['title'] == "example.txt"):      file_on_drive = True      fileID = file['id']    # fine if  # fine for  if file_on_drive:  # Sovrascrive il file esistente nell'unità Google."""    file1 = drive.CreateFile({'id': fileID})    strFileHandling = "Aggiornato"  else:    file1 = drive.CreateFile({"mimeType": "text/csv",                             "parents": [{"kind": "drive#fileLink",                                         "id": folderID}]})    strFileHandling = "Creato"  # fine if  # creazione del collegamento al file nell'ambiente di esecuzione:  file1.SetContentFile("example.txt")  # copia del file su Google Drive:  file1.Upload()  print(f'{strFileHandling} file %s con mimeType %s' % (file1['title'], file1['mimeType']))else:  print("cartella non trovata")# fine if

Eseguendo il codice sopra verrà creato un nuovo file nella cartella condivisa o verrà aggiornato (sovrascritto) il file quando il file viene trovato.

Creazione di uno spazio di lavoro

C’è una seconda ragione per utilizzare l’ID del collegamento per trovare l’ID di destinazione e cioè trovare elementi sotto la cartella condivisa. Come accennato in precedenza, Google Drive gestisce tutto per ID, e l’ID del collegamento non ha figli, quindi utilizzando questo ID per trovare nuovi elementi si otterrà una lista vuota. Ciò può essere testato includendo il nome della cartella “ExternalData” nella prima lista di cartelle; la prima lista non troverà questa cartella. Tuttavia, riavviando il ciclo con l’ID di destinazione verrà trovata questa cartella.

Nello snippet di codice sottostante, viene creata una nuova lista di cartelle, utilizzando i nomi delle cartelle sotto il nome della cartella “Condiviso con me”. La cartella “ExternalData” è disponibile (vedere Figura 1), ma “NewDataFolder” non è ancora stata creata.

# Aggiorna questi con la tua struttura:# ... DataSviluppo/ExternalData/__CoLab_Notebook # Impostazione della cartella di lavoro:folderList2 = ["ExternalData", "NewDataFolder"]

Possiamo utilizzare la stessa struttura del ciclo come prima, ma ora anziché partire dalla ROOT, partiamo con l’ID di destinazione, e il ciclo troverà la cartella “ExternalData”, ma non la nuova cartella dei dati.

Poiché la cartella di lavoro non esiste ancora, possiamo utilizzare drive_service.files per creare questa nuova cartella, e con lo stesso metodo, tutti i file che devono essere trasferiti dall’ambiente di esecuzione nella cartella “Condiviso con me”.

def create_folder_in_folder(folder_name, parent_folder_id, drive_service):
    file_metadata = {
        'name' : folder_name,
        'parents' : [parent_folder_id],
        'mimeType' : 'application/vnd.google-apps.folder'
    }
    file = drive_service.files().create(body=file_metadata, supportsAllDrives=True,
                                        fields='id').execute()
    print ('ID della cartella: %s' % file.get('id'))

if WorkingFolderID == 0:   # fileID è l'ID del genitore della ricerca precedente
    create_folder_in_folder("NuovaCartellaDati", fileID, drive_service)

Punti principali: Il File System di Google Drive è basato sugli ID e tutti gli oggetti hanno un ID. Gli oggetti “Condivisi con me” non sono disponibili in Google Colab, ma attraverso un “Shortcut” possiamo accedervi e, trovando l’ID di destinazione associato, possiamo lavorare direttamente sulla cartella “Condivisa con me”, inclusi gli oggetti presenti nella cartella condivisa inizialmente con noi.

Conclusioni

In questo articolo, abbiamo coperto alcuni aspetti essenziali del lavoro con cartelle condivise, tra cui:

  1. Configurazione della gestione dei file locali: Abbiamo iniziato il processo con la ricezione di un invito a contribuire a una directory di Google Drive designata e mostrato come strutturare il proprio sistema di file locale per migliorare l’efficienza collaborativa.
  2. Configurazione di Google Colab per la collaborazione: Abbiamo discusso i vantaggi dell’utilizzo di Google Colab, un ambiente di programmazione collaborativo in Python, e come configurarlo per la collaborazione su progetti.
  3. Importazione dei moduli e dei pacchetti necessari: Abbiamo fornito esempi di codice per l’importazione di moduli e pacchetti essenziali, tra cui l’autorizzazione di Google, pydrive per semplificare le operazioni dell’API di Google Drive e il client dell’API di Google per funzionalità avanzate.
  4. Gestione dei file nel notebook: Hai visto come gestire i file all’interno dell’ambiente di Google Colab, inclusa la creazione e lo spostamento dei file tra il tuo ambiente locale e le cartelle condivise utilizzando l’ID condiviso e l’ID di destinazione.
  5. Trovare file e creare spazi di lavoro: Ci siamo addentrati nel processo di ricerca dei file all’interno di cartelle condivise utilizzando gli ID di destinazione e la creazione di nuove cartelle e spazi di lavoro per i tuoi progetti.

Spero che questa guida sul lavoro con cartelle e file condivisi tra organizzazioni sia stata utile e abbia fornito alcuni spunti su come lavorare con file e cartelle in una cartella condivisa.

Ti ringrazio per la lettura, spero che questo post ti abbia aiutato a risolvere un problema o ti abbia dato un’idea per il prossimo progetto.

Link al notebook di Google CoLab: gist

Disclaimer: Il codice utilizzato in questo esempio non è ottimizzato, ma è scritto per illustrare il processo (ogni suggerimento su come migliorare il codice è benvenuto sulle pagine di gitHub che ospitano questo notebook).