Błąd "Illegal access to removed OSM object"

0

Witam

Mam problem ze skryptem. Nie jestem biegły w Python więc zwracam się o pomoc.
Skrypt inicjuje obiekt handler, wczytuje do niego dane z plika, wtedy jeszcze w debuggerze widze w nim dane, ale zaraz potem tuż przed wejściem do funkcji write_osm_file obiekt handler tak jakby już nie istniał albo miał inny problem.
Jak pisałem jestem słaby w python więc proszę o pomoc.
Poniżej zrzut z konsoli i skrypt.

KONSOLA:

c:\3DTiles>python filter.py
Applying file...
Added way with building tag: id=961961143, nodes=5
  Node ref: ref=8898381795
  Node ref: ref=8898381989
  Node ref: ref=8898381128
  Node ref: ref=8898381368
  Node ref: ref=8898381795
  Tag: k=addr:city, v=Warszawa
  Tag: k=addr:city:simc, v=0918123
  Tag: k=addr:housenumber, v=19
  Tag: k=addr:postcode, v=02-995
  Tag: k=addr:street, v=Prętowa
  Tag: k=building, v=detached
  Tag: k=building:levels, v=2
  Tag: k=source, v=www.geoportal.gov.pl
  Tag: k=source:addr, v=gugik.gov.pl
Finished applying file.
Writing buildings to file...
Skipping element due to invalid id access: Illegal access to removed OSM object (element: {'_pyosmium_data': <osmium.osm._osm.COSMWay object at 0x000002A6147FF570>, 'tags': osmium.osm.TagList({<invalid>}), '_nodes': osmium.osm.WayNodeList([<invalid>])})
Found 1 buildings.

SKRYPT:

import osmium as osm
import xml.etree.ElementTree as ET

class BuildingHandler(osm.SimpleHandler):
    def __init__(self):
        osm.SimpleHandler.__init__(self)
        self.buildings = []

    def node(self, n):
        try:
            if 'building' in n.tags and n.location.valid():
                self.buildings.append(n)
                print(f"Added building node: id={n.id}, lat={n.location.lat}, lon={n.location.lon}")
        except Exception as e:
            print(f"Error processing node: id={n.id}, error={e}")

    def way(self, w):
        try:
            if 'building' in w.tags or 'building' in w.tags.get('other_tags', ''):
                self.buildings.append(w)
                print(f"Added way with building tag: id={w.id}, nodes={len(w.nodes)}")
                for node in w.nodes:
                    print(f"  Node ref: ref={node.ref}")
                for tag in w.tags:
                    print(f"  Tag: k={tag.k}, v={tag.v}")
        except Exception as e:
            print(f"Error processing way: id={w.id}, error={e}")

    def relation(self, r):
        try:
            if 'building' in r.tags:
                self.buildings.append(r)
                print(f"Added building relation: id={r.id}, members={len(r.members)}")
        except Exception as e:
            print(f"Error processing relation: id={r.id}, error={e}")

def write_osm_file(filename, elements):
    root = ET.Element("osm", version="0.6")
    
    for element in elements:
        try:
            if isinstance(element, osm.osm.Node):
                element_id = str(element.id)
                print(f"Node element_id: {element_id}")
                if int(element_id) == -1:
                    raise RuntimeError("Invalid id")
                node = ET.SubElement(root, "node", id=element_id, lat=str(element.location.lat), lon=str(element.location.lon))
                for tag in element.tags:
                    ET.SubElement(node, "tag", k=tag.k, v=tag.v)
                print(f"Processed node: id={element_id}")
            elif isinstance(element, osm.osm.Way):
                element_id = str(element.id)
                print(f"Way element_id: {element_id}")
                if int(element_id) == -1:
                    raise RuntimeError("Invalid id")
                way = ET.SubElement(root, "way", id=element_id)
                print(f"Processing way: id={element_id}")
                for node_ref in element.nodes:
                    print(f"  Adding node_ref: ref={node_ref.ref}")
                    ET.SubElement(way, "nd", ref=str(node_ref.ref))
                for tag in element.tags:
                    print(f"  Adding tag: k={tag.k}, v={tag.v}")
                    ET.SubElement(way, "tag", k=tag.k, v=tag.v)
                print(f"Processed way: id={element_id}, nodes={len(element.nodes)}")
            elif isinstance(element, osm.osm.Relation):
                element_id = str(element.id)
                print(f"Relation element_id: {element_id}")
                if int(element_id) == -1:
                    raise RuntimeError("Invalid id")
                relation = ET.SubElement(root, "relation", id=element_id)
                for member in element.members:
                    ET.SubElement(relation, "member", type=member.type, ref=str(member.ref), role=member.role)
                for tag in element.tags:
                    ET.SubElement(relation, "tag", k=tag.k, v=tag.v)
                print(f"Processed relation: id={element_id}, members={len(element.members)}")
            else:
                print(f"Unknown element type: {type(element)}")
        except RuntimeError as e:
            print(f"Skipping element due to invalid id access: {e} (element: {element.__dict__})")
        except Exception as ex:
            print(f"Unexpected error for element: {ex} (element: {element.__dict__})")

    tree = ET.ElementTree(root)
    tree.write(filename, encoding="utf-8", xml_declaration=True)

if __name__ == "__main__":
    # Initialize the handler
    handler = BuildingHandler()

    # Read the OSM file
    print("Applying file...")
    handler.apply_file(r'C:\3DTiles\map.osm')
    print("Finished applying file.")

    # Save the filtered buildings to a new file
    print("Writing buildings to file...")
    write_osm_file(r'C:\3DTiles\filtered_buildings.osm', handler.buildings)

    print(f"Found {len(handler.buildings)} buildings.")
1

Sformatuj to porządnie, jak wygląda metoda, apply_file?

0

@lion137: Dzięki za odpowiedź. Jak pisałem nie jestem biegły w python, w zasadzie programowaniem zajmowałem się 20 lat temu, głównie w C++. Teraz rozumiem działanie tego skryptu ale nie mam siły przebijać się przez takie problemy. W sensie że zawodowo robię zupełnie coś innego, a taki skrypt potrzebujemy w pracy. Jeśli to możliwe to może mógłbyś mi pomóc poza forum za $. Potem pewnie też będę się zwracał o pomoc. Jak sytuacja w firmie będzie się rozwijać.

2

Tu problemem jest to, że we write_osm_file odwołujesz się do obiektów (handler.buildings), które mogą już nie żyć 😱
Prostym rozwiązaniem byłoby zrobienie głębokiej kopii obiektów, które dodajesz do buildings.

1 użytkowników online, w tym zalogowanych: 0, gości: 1