2017-03-04 48 views
2

我正在尋找一種通用的方法來爲需要文件名的函數使用URL。我對此感到困惑,但它有點複雜,容易出錯。如何在Python中提供需要文件名的函數的URL

在這種情況下,我的功能是read_filegeopandas,但它在任何情況下都是同樣的問題。

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) 

這樣的作品,並沒有看太可怕了,但我不得不嘗試一堆找到它,因爲輕微的變種提高OSError: no such file or directory,由於臨時文件的壽命;但我也不想用永久文件混淆文件系統。

這種失敗:

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

gpd.read_file(as_file(URL)) 

即使這樣:

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

gpd.read_file(as_file(URL).name) 

有一個比較明顯的,令人難忘的,還是防彈的方式?

+0

你可以使用['contextlib.contextmanager'(https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager)和「機智」 h'。對不起,沒時間提供更好的答案。 –

回答

2

您可以使用上下文管理器來管理臨時文件的生命週期:

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 

注:with NamedTemporaryFile() as tfile將只使用Python 3下工作,否則你必須確保它清理自己正確爲Python 2.

用法:

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

就是這樣,謝謝!實際上,它似乎也沒有'tfile.flush()'。 –

+1

如果寫入的字節太少,緩衝區可能不會刷新,並且geopandas會嘗試讀取文件中的空白或部分數據。嘗試用''hello'替換'requests.get(url).content'並查看'gpd.read_file'得到了什麼。 –

相關問題