2017-03-04 3 views
2

Je cherche une recette générale pour utiliser une URL pour une fonction qui attend un nom de fichier. J'en ai laissé perplexe, mais c'est un peu complexe et facile de se tromper.Comment fournir l'URL à la fonction nécessitant un nom de fichier en Python

Dans ce cas, ma fonction est read_file de geopandas, mais ce serait le même problème dans tous les cas.

import tempfile, requests 
import geopandas as gpd 

def as_file(url): 
    tfile = tempfile.NamedTemporaryFile() 
    tfile.write(requests.get(url).content) 
    return tfile 

URL = 'https://raw.githubusercontent.com/bowmanmc/ohiorepresents/master/data/congressional.min.json' 
tf = as_file(URL) 
gpd.read_file(tf.name) 

qui fonctionne et ne semble pas trop terrible, mais je devais expérimenter un tas de trouver, parce que de légères variantes soulèvent OSError: no such file or directory, en raison de la durée de vie tempfiles; Pourtant, je ne veux pas non plus encombrer le système de fichiers avec des fichiers permanents.

Cela échoue:

def as_file(url): 
    tfile = tempfile.NamedTemporaryFile() 
    tfile.write(requests.get(url).content) 
    return tfile.name 

gpd.read_file(as_file(URL)) 

et même ceci:

def as_file(url): 
    tfile = tempfile.NamedTemporaryFile() 
    tfile.write(requests.get(url).content) 
    return tfile 

gpd.read_file(as_file(URL).name) 

Y at-il une manière plus évidente, mémorable, ou l'épreuve des balles?

+0

Vous pouvez utiliser [ 'contextlib.contextmanager'] (https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager), et 'wit h'. Désolé pas le temps de fournir une meilleure réponse. –

Répondre

2

Vous pouvez utiliser un gestionnaire de contexte pour gérer la durée de vie du fichier temporaire:

from contextlib import contextmanager 

@contextmanager 
def as_file(url): 
    with tempfile.NamedTemporaryFile() as tfile: 
     tfile.write(requests.get(url).content) 
     tfile.flush() 
     yield tfile.name 

Note: Le with NamedTemporaryFile() as tfile ne fonctionne qu'avec Python 3. Sinon, vous devrez vous assurer qu'il nettoie correctement vous pour Python 2.

utilisation:

with as_file(URL) as filename: 
    gpd.read_file(filename) 
+1

C'est tout, merci! En fait, cela semble fonctionner sans le 'tfile.flush()'. –

+1

Si trop peu d'octets sont écrits, le tampon peut ne pas être vide et geopandas essaiera de lire les données vides ou partielles du fichier. Essayez de remplacer 'requests.get (url) .content' par''hello'' et voyez ce que 'gpd.read_file' obtient. –