Как исправить ValueError: чтение исключения закрытого файла?

Это просто Python 3 сценарий:

import urllib.request

host = "scholar.google.com"
link = "/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0"
url = "http://" + host + link
filename = "cite0.bib"
print(url)
urllib.request.urlretrieve(url, filename)

вызывает это исключение:

Traceback (most recent call last):
  File "C:UsersricardoDesktopGoogle-ScholarBibTextest2.py", line 8, in <module>
    urllib.request.urlretrieve(url, filename)
  File "C:Python32liburllibrequest.py", line 150, in urlretrieve
    return _urlopener.retrieve(url, filename, reporthook, data)
  File "C:Python32liburllibrequest.py", line 1597, in retrieve
    block = fp.read(bs)
ValueError: read of closed file

Я думал, что это может быть временная проблема, поэтому я добавил простую обработку исключений, например:

import random
import time
import urllib.request

host = "scholar.google.com"
link = "/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0"
url = "http://" + host + link
filename = "cite0.bib"
print(url)
while True:
    try:
        print("Downloading...")
        time.sleep(random.randint(0, 5))
        urllib.request.urlretrieve(url, filename)
        break
    except ValueError:
        pass

но это просто выводит Downloading... ad infinitum.

1 ответов


Ваш URL возвращает ошибку кода 403 и, по-видимому,urllib.запрос.urlretrieve не очень хорошо обнаруживает все ошибки HTTP, потому что он использует urllib.request.FancyURLopener и эта последняя попытка проглотить ошибку, вернув urlinfo вместо ошибки.

о исправлении, если вы все еще хотите использовать urlretrieve вы можете переопределить FancyURLopener, как это (код включен, чтобы также показать ошибку):

import urllib.request
from urllib.request import FancyURLopener


class FixFancyURLOpener(FancyURLopener):

    def http_error_default(self, url, fp, errcode, errmsg, headers):
        if errcode == 403:
            raise ValueError("403")
        return super(FixFancyURLOpener, self).http_error_default(
            url, fp, errcode, errmsg, headers
        )

# Monkey Patch
urllib.request.FancyURLopener = FixFancyURLOpener

url = "http://scholar.google.com/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0"
urllib.request.urlretrieve(url, "cite0.bib")

еще и это что?!--16-->рекомендую можно использовать urllib.request.urlopen вот так:

fp = urllib.request.urlopen('http://scholar.google.com/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0')
with open("citi0.bib", "w") as fo:
    fo.write(fp.read())