1

I am trying to read shapefiles. I have handled the error that could occur when reading a shapefile by writing a function read_gdf (see code below) but I am still getting an error UnicodeDecodeError: 'utf-8' codec can't...

from pathlib import Path

def read_gdf(file:str,crs:str,current_crs:str)->gpd.GeoDataFrame:
    #Read data
    collection = list(fiona.open(file,'r'))
    df1 = pd.DataFrame(collection)

    
    df1['isvalid'] = df1['geometry'].apply(lambda x: isvalid(x))
    df1 = df1[df1['isvalid'] == 1]
    collection = json.loads(df1.to_json(orient='records'))

    #Convert to geodataframe
    return gpd.GeoDataFrame.from_features(collection, crs=current_crs).to_crs(crs)

gdfs = []
for file in Path(rootdir).rglob("*.shp"):
    print('file is', file)            
    gdf = read_gdf(file, crs,current_crs=current_crs)
    gdf.columns = map(str.lower, gdf.columns)                
    gdfs.append(gdf)

How can I ignore the line that has the error and continue reading the rest of the shapefile?

4
  • are you sure the Shapefile (or infact dbf) is in UTF-8, if it isn't then you'll need to tell the reader
    – Ian Turton
    Commented Jun 20, 2023 at 8:47
  • When I try encoding=”iso-8859-1” i manage to read the shape file. However, will this encoding damage the reading of the geometry? Why does it not work with the default encoding which is UTF-8? what is the difference between UTF-8 and ”iso-8859-1”
    – bravopapa
    Commented Jun 20, 2023 at 9:45
  • 1
    The encoding only applies to the attributes of the features not the geometry which are binary. As for the difference between the two one is a standard and the other is used by Microsoft ;-)
    – Ian Turton
    Commented Jun 20, 2023 at 11:15
  • Thanks a lot. As long as the geometry is not impacted then I am happy
    – bravopapa
    Commented Jun 20, 2023 at 11:17

2 Answers 2

2

To solve the issue, change the encoding to encoding='iso-8859-1'

def read_gdf(file:str,crs:str,current_crs:str)->gpd.GeoDataFrame:
    #Read data
    collection = list(fiona.open(file,'r',  encoding='iso-8859-1'))
    df1 = pd.DataFrame(collection)

    
    df1['isvalid'] = df1['geometry'].apply(lambda x: isvalid(x))
    df1 = df1[df1['isvalid'] == 1]
    collection = json.loads(df1.to_json(orient='records'))

    return gpd.GeoDataFrame.from_features(collection, crs=current_crs).to_crs(crs)
1
  • 1
    Accept your own answer with the checkbox
    – Bera
    Commented Jul 9, 2023 at 17:16
2

Try directly using GeoPandas, without Fiona (GeoPandas use Fiona) and Pandas.

import geopandas as gpd
for file in pathlib.Path(directory).rglob('**/*.shp'):
     print('file is', file)   
     # open the shapefile
     try:
        df1 = gpd.read_file(file)
        # all changes in df1
     except:
        print("error")
7
  • A quick question please: Does your suggestion skip the line or the file in case of an error? The except catches the error but does it skip the line only or the whole file?
    – bravopapa
    Commented Jun 20, 2023 at 14:14
  • yes, you can modify the resulting GeoDataFrame, (delete rows, add rows, modify values)
    – gene
    Commented Jun 20, 2023 at 14:19
  • There are many examples in GisSE
    – gene
    Commented Jun 20, 2023 at 14:27
  • I think my question was misunderstood. I am asking if the except skips the line or the whole file. Thanks
    – bravopapa
    Commented Jun 20, 2023 at 14:30
  • In this case, the whole file, but you can modify the condition
    – gene
    Commented Jun 20, 2023 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.