Действительно в соответствии с документацией API , первый аргумент votable.parse
- это либо имя файла, либо читаемый файлоподобный объект. Это не определяет это точно, но, очевидно, файл также должен быть seekable , что означает, что он может быть прочитан с произвольным доступом.
Объект HTTPResponse
, возвращаемый urlopen
,на самом деле это файлоподобный объект с методом .read()
, поэтому в принципе можно было бы напрямую перейти к parse()
, но я обнаружил, что он должен быть доступен для поиска:
fltr = 'http://svo2.cab.inta-csic.es/theory/fps/fps.php?ID=2MASS/2MASS.H'
u = urlopen(fltr)
>>> parse(u)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "astropy/io/votable/table.py", line 135, in parse
_debug_python_based_parser=_debug_python_based_parser) as iterator:
File "/usr/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "astropy/utils/xml/iterparser.py", line 157, in get_xml_iterator
with _convert_to_fd_or_read_function(source) as fd:
File "/usr/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "astropy/utils/xml/iterparser.py", line 63, in _convert_to_fd_or_read_function
with data.get_readable_fileobj(fd, encoding='binary') as new_fd:
File "/usr/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "astropy/utils/data.py", line 210, in get_readable_fileobj
fileobj.seek(0)
io.UnsupportedOperation: seek
Таким образом, вам нужно обернуть данные в доступный для поиска файловый объект. В соответствии с тем, что написал @keflavich, вы можете использовать io.BytesIO
(io.StringIO
не будет работать, как описано ниже).
Оказывается, что нет никакой причины явно декодировать данные UTF-8 в Unicode. Я избавлю пример, но, попробовав сам, выясняется, что parse()
работает с необработанными байтами (что я нахожу немного странным, но все в порядке). Таким образом, вы можете прочитать все содержимое URL в io.BytesIO
, который представляет собой просто файл-подобный объект в памяти, который поддерживает произвольный доступ:
>>> u = urlopen(fltr)
>>> s = io.BytesIO(u.read())
>>> v = parse(s)
WARNING: W42: None:2:0: W42: No XML namespace specified [astropy.io.votable.tree]
>>> v.get_first_table().to_table(use_names_over_ids=True)
<Table masked=True length=58>
Wavelength Transmission
AA
float32 float32
---------- ------------
12890.0 0.0
13150.0 0.0
... ...
18930.0 0.0
19140.0 0.0
Это, как правило, путь в Pythonделать что-то с данными, как будто это файл, без записи фактического файла в файловую систему.
Обратите внимание, однако, что это не сработает, если весь файл не помещается в памяти. В этом случае вам все еще может потребоваться записать его на диск. Но если это просто для какой-то временной обработки и вы не хотите засорять свой диск tmp.xml
, как в вашем примере, вы всегда можете использовать модуль tempfile
, чтобы, среди прочего, создавать временные файлыкоторые автоматически удаляются, когда они больше не используются.