开发者

Python: Inject attribute into object created by C library

开发者 https://www.devze.com 2023-02-13 16:23 出处:网络
I\'m trying to inject an attribute into lxml.etree._Element, but as that module is completely implemented in C, setattr fails:

I'm trying to inject an attribute into lxml.etree._Element, but as that module is completely implemented in C, setattr fails:

Traceback (most recent call last):
[...]
    setattr(node.getroottree().getroot(), "attributeName", value)
AttributeError: 'lxml.etree._Element' object has no attribute 'attributeName'

The use case: I have a function that extracts text from a XML file by XPath and replaces $(ENV)-like matches by the corresponding value. Therefore I don't want to have to pass the variables dictionary (e.g. {"ENV" : "replacement"} to that function each time. Instead it would be easier to just have an attribute at a fixed place (XML root in my code). I could do a dumb workaround but injecting a Python attribute would be the best way. I cannot use a global variable because each XML file can have different varia开发者_运维百科ble values.

So, any way to inject something into C-based classes/objects?


You generally can't, as instances of C-defined types typically don't have per-instance __dict__ entries to hold arbitrary attributes.

A workaround for cases when a subclass or wrapper class won't work is to create a helper dictionary at the module level that maps the object you have to additional information. If the object you have isn't hashable, you can use id(obj) instead.

So, for example, you could store a dictionary associated with the id of each root object:

# Module level, setting up the data store
from collections import defaultdict
extra_info = defaultdict(dict) # Creates empty dicts for unknown keys

# Saving the info
root = node.getroottree().getroot()
extra_info[id(root)]["ENV"] = "replacement"

# Retrieving it later
root = node.getroottree().getroot()
info = extra_info[id(root)]
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号