-
-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AttributeError: 'Reader' object has no attribute 'shp' #120
Comments
Thanks for raising the issue! I created #121 for the syntaxwarning and some other style improvements. You have installed the right packages. I can reproduce the AttributeError, but it creates a correctly topojson. I'm a bit puzzled why the AttributeError is raised. I tried to debug it a bit, but in the end its not much more (at least it should not be much more) than: import topojson as tp
import shapefile
import copy
data = shapefile.Reader("tests/files_shapefile/southamerica.shp")
data = copy.deepcopy(data.__geo_interface__)
topo = tp.Topology([data])
topo.toposimplify(4).to_svg() And like this it doesn't give an issue. You also could do: import fiona
with fiona.open("tests/files_shapefile/southamerica.shp") as data:
topo = tp.Topology(data)
topo.toposimplify(4).to_svg() or import geopandas as gpd
data = gpd.read_file("tests/files_shapefile/southamerica.shp")
topo = tp.Topology(data)
topo.toposimplify(4).to_svg() Which also will not give an AttributeError. But you are completely right about the AttributeError using |
I have no idea what's going on or how to fix it, I just wanted to report it. Like you say the topo object actually looks fine so I'm just leaving the ugly error in my notebook and moving forward. |
Fair enough. Sorry for the not-so great aesthetic notebook pleasure. |
No worries! Hope the report was useful and not annoying, and thanks for the library, very useful |
Came across this issue and thought it was very weird since i know for sure pyshp’s Reader should always have a .shp attribute; it’s set at init and is never explicitly deleted. But i think i figured it out. In the example, the Topology class is given the entire pyshp Reader instance as its input data. I followed the init code through several layers of subclasses until finally in the extract.Extract class it does a try-except deepcopy of the input data, before it sends it to the _extractor method where it eventually looks for the geo interface. What i think is happening is the deepcopy succeeds in copying the Reader class, except it «does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types». Indeed .shp is a file object so then it probably doesn’t copy that attribute. Which is why later when the deepcopied Reader gets garbage collected and tries to close the .shp file it can’t find it and raises an exception. I’m not fully sure why you have the deepcopy there in the first place, except for a link in the code to a geopandas github issue. Would it be possible to do a more targeted check specific to the geopandas issue, so it only does the deepcopy for that use case? Also, i noticed there are other attempts at deepcopy of the geo interface dict later on, which i’m wondering might be an unnecessary copy of data (and might be a bottleneck/slowdown for very large datasets) since presumably all the data gets copied into numpy arrays pretty soon after anyway? |
Thanks so much for digging this deep. The GeoPandas try/except part was because of GeoPandas not directly supporting deepcopy on For what it is worth, per documentation, https://mattijn.github.io/topojson/how-it-works.html#extract, you can skip all subclasses and work directly with the Extract class as such: from topojson.core.extract import Extract
import shapefile
data = shapefile.Reader("tests/files_shapefile/southamerica.shp")
Extract(data) This probably makes debugging easier. I also can reproduce the pyshp AttributeError. Its really weird, look: data = shapefile.Reader("tests/files_shapefile/southamerica.shp")
# https://github.com/mattijn/topojson/blob/master/topojson/core/extract.py#L73
copydata = data # just reassigning, no copies
geom = copy.deepcopy(copydata.__geo_interface__)
# BOOM:
But like this there is no raising of data = shapefile.Reader("tests/files_shapefile/southamerica.shp")
geom = copy.deepcopy(data.__geo_interface__)
# ALL FINE |
So I'm not sure I understand your reassigning example, but after some more tests deepcopy is definitely the culprit, but it only shows up when it's inside the try-except clause:
I think probably what happens is that deepcopy is able to partially copy the Reader class except for the .shp and other attributes since deepcopy cannot copy BytesIO objects. When that partially created Reader class later gets garbage collected (since the deepcopy eventually fails), which is when it runs So in terms of a solution, I guess just doing a more selective check for the geopandas case around L76 (or dropping it entirely now that geopandas has fixed it) would do it? I'll probably also add to pyshp a try-except clause in |
When I run the shapefile import example from the docs, I get a couple errors. The first two are
SyntaxWarning
s from topojson (would you like me to submit a PR?), and the more concerning one is anAttributeError
:After I installed
fiona
(which I just guessed from the code snippet above), theSyntaxError
s went away, but theAttributeError
remained.Here are the libraries I installed before trying to use topojson:
pip install topojson simplification altair geopandas ipywidgets pyshp geojson fiona
Am I missing some other library that I need?
The text was updated successfully, but these errors were encountered: