2016-02-12 43 views
2

(見底部更新)無法解析在python一個協議緩衝區文件

TilemakerOpenStreetMap程序來生成Mapbox vector tiles(它們本身protocol buffers(PBF)文件)從OSM pbf數據文件。我編譯了它並用它創建了矢量圖塊的目錄。我無法用Python解析這些文件。

我創建的載體瓷磚:

tilemaker input.pbf --output=tiles/ 

然後,我創建了一個簡單的Python程序,以這種方式基於Google's Protocol Buffers Python Tutorial

編譯.proto文件:

mkdir py 
touch py/__init__.py 
protoc --proto_path=include --python_out=./py ./include/osmformat.proto 
protoc --proto_path=include --python_out=./py ./include/vector_tile.proto 

這python程序pyread.py不起作用:

import sys 
import py.vector_tile_pb2 

with open(sys.argv[1]) as fp: 
    pbf_file_contents = fp.read() 

tile = py.vector_tile_pb2.Tile() 
tile.ParseFromString(pbf_file_contents) 

這試圖運行它的時候是錯誤:

$ python pyread.py ./tiles/13/3932/2588.pbf 
Traceback (most recent call last): 
    File "pyread.py", line 8, in <module> 
    tile.ParseFromString(pbf_file_contents) 
    File "/home/rory/.local/lib/python2.7/site-packages/google/protobuf/message.py", line 186, in ParseFromString 
    self.MergeFromString(serialized) 
    File "/home/rory/.local/lib/python2.7/site-packages/google/protobuf/internal/python_message.py", line 841, in MergeFromString 
    if self._InternalParse(serialized, 0, length) != length: 
    File "/home/rory/.local/lib/python2.7/site-packages/google/protobuf/internal/python_message.py", line 866, in InternalParse 
    new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) 
    File "/home/rory/.local/lib/python2.7/site-packages/google/protobuf/internal/decoder.py", line 827, in SkipField 
    return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end) 
    File "/home/rory/.local/lib/python2.7/site-packages/google/protobuf/internal/decoder.py", line 797, in _RaiseInvalidWireType 
    raise _DecodeError('Tag had invalid wire type.') 
google.protobuf.message.DecodeError: Tag had invalid wire type. 

protoc命令從協議型緩衝庫。我從Google的頁面(鏈接到Github)下載了最新版本(2.6.1),並編譯了&安裝它。該protoc調用就像Tilemaker Makefile does一樣。

發生了什麼事?我如何在python中讀取這個協議緩衝區文件?


UPDATE進一步的調查讓我覺得,我的假設之一可能是錯的。也就是說,tilemaker命令生成了一個有效的protobuf文件。我有一些vector tiles from Mapzen,應該有相同的格式和非常相似的數據。 但是該格式與python pyread.py命令以及protoc --decode_rawprotoc --decode=vector_tile.Tile ./include/vector_tile.proto一起使用。因此,我認爲問題出在我看到的文件上。

+0

是否從OpenStreetMap的protobuffer具有相同的版本作爲protoc用於生成的.py? –

+0

在這個例子中。 Tilemaker程序的Makefile在我的機器上調用'protoc'命令來生成一個'.proto'文件的C++文件。我使用相同的'protoc'二進制文件和相同的'.proto'文件來生成python文件,並且它不起作用。 – Rory

+0

你在Windows上嗎?如果是這樣,您需要以二進制模式打開。 'open(filename,「rb」)'。 (這是在所有系統上執行此操作的好主意,但它只對Windows非常重要。) –

回答

1

我認爲問題是OpenStreetMap的.pbf格式是而不是原始protobuf。見我的回答您的其他問題:

https://stackoverflow.com/a/35384238/2686899

+0

感謝您的洞察力:OSM pbf格式。這就說得通了。但是在這種情況下,結果是[MapBox Vector Tiles格式](https://github.com/mapbox/vector-tile-spec),而不是[OSM PBF](http://wiki.openstreetmap.org/wiki/PBF_Format)。和[最新(2.1)規格](https://github.com/mapbox/vector-tile-spec/tree/master/2。1)意味着它是一個純協議緩衝文件。 – Rory

+0

@Rory好吧,'protoc --decode_raw

+0

查看我對該問題所做的更新。 'protoc --decode_raw'在該文件上不起作用。但它(和我的程序)處理另一個同樣格式的文件。因此,你一定是對的。該文件不是有效的protobuf文件。 – Rory