【发布时间】:2021-06-03 06:36:17
【问题描述】:
我知道这个问题已经被问过很多次了,但我使用的是 Python 3.9.5,我在这里找到的解决方案都没有奏效。
我的请求非常简单:获取一个对象及其子对象的所有可用对象名称的 XML 树列表。
为了说明这一点,我安装了许多 Python 模块,并想知道模块提供的所有内容。
dir() 方法返回一个对象内部的属性名称列表,它返回一个字符串列表。
type() 方法返回对象的类型,一些子对象本身有子对象,我想要一个 XML 树列出最低级别对象的所有名称(并且只有名称,而不是值),即int、bool、float、str、set、list、tuple、dict 等类型。
例如,假设我们有一个名为obj 的对象,obj 具有三个属性:a、b 和c。 a 没有唯一属性,b 有两个唯一属性:d 和 e,d 和 e 没有唯一属性,c 有三个唯一属性:@ 987654345@、g 和h,以及f 有一个名为i 的唯一属性,g 有一个名为j 的唯一属性,而h 有一个名为k 的唯一属性。 i、j 和 k 是内置类型。
现在结果应该是这样的:
<?xml version="1.0" ?>
<elem name='obj'>
<attr name='a' />
<elem name='obj.b'>
<attr name='d' />
<attr name='e' />
</elem>
<elem name='obj.c'>
<elem name='obj.c.f'>
<attr name='i' />
</elem>
<elem name='obj.c.g'>
<attr name='j' />
</elem>
<elem name='obj.c.h'>
<attr name='k' />
</elem>
</elem>
</elem>
标有elem的元素是具有__dict__属性的自定义类,标有attr的元素没有__dict__s。
现在要获取obj 的属性,我们使用dir(obj),它会返回一个字符串列表['a','b','c']。
要获取obj.c 的属性,我们必须手动输入dir(obj.c),因为'c' 是一个字符串,而'obj.c' 不在vars() 中。
现在要将字符串转换为名称,我们必须使用eval()。 dir(eval('obj.c')) 正确执行。
但是要递归地使用该命令,我们必须使用类似这样的东西:
dir(eval(f'{obj.__name__}.{attr}'))
但是__name__ 属性没有给出其全名(如obj.c.f),如果名称包含__,则__name__ 值将没有__s。更何况有些对象没有__name__ 属性。
那么如何做到这一点呢?
更新
我已经取得了一些初步的成功:
import inspect
from xml.dom.minidom import Document
doc = Document()
def treeobj(obj, path=''):
fullname = f'{path}.{obj.__name__}'.lstrip('.')
node = doc.createElement('elem')
node.setAttribute('name', fullname)
for attr in dir(obj):
if not attr.startswith('__'):
val = getattr(obj, attr)
if inspect.isclass(val):
elem = treeobj(val, fullname)
else:
elem = doc.createElement('attr')
elem.setAttribute('name', attr)
node.appendChild(elem)
return node
这是print(treeobj(os).toprettyxml())的输出:
<elem name="os">
<elem name="os.DirEntry">
<attr name="inode"/>
<attr name="is_dir"/>
<attr name="is_file"/>
<attr name="is_symlink"/>
<attr name="name"/>
<attr name="path"/>
<attr name="stat"/>
</elem>
<attr name="F_OK"/>
<elem name="os.GenericAlias"/>
<elem name="os.Mapping">
<attr name="_abc_impl"/>
<attr name="get"/>
<attr name="items"/>
<attr name="keys"/>
<attr name="values"/>
</elem>
<elem name="os.MutableMapping">
<attr name="_MutableMapping__marker"/>
<attr name="_abc_impl"/>
<attr name="clear"/>
<attr name="get"/>
<attr name="items"/>
<attr name="keys"/>
<attr name="pop"/>
<attr name="popitem"/>
<attr name="setdefault"/>
<attr name="update"/>
<attr name="values"/>
</elem>
<attr name="O_APPEND"/>
<attr name="O_BINARY"/>
<attr name="O_CREAT"/>
<attr name="O_EXCL"/>
<attr name="O_NOINHERIT"/>
<attr name="O_RANDOM"/>
<attr name="O_RDONLY"/>
<attr name="O_RDWR"/>
<attr name="O_SEQUENTIAL"/>
<attr name="O_SHORT_LIVED"/>
<attr name="O_TEMPORARY"/>
<attr name="O_TEXT"/>
<attr name="O_TRUNC"/>
<attr name="O_WRONLY"/>
<attr name="P_DETACH"/>
<attr name="P_NOWAIT"/>
<attr name="P_NOWAITO"/>
<attr name="P_OVERLAY"/>
<attr name="P_WAIT"/>
<elem name="os.PathLike">
<attr name="_abc_impl"/>
</elem>
<attr name="R_OK"/>
<attr name="SEEK_CUR"/>
<attr name="SEEK_END"/>
<attr name="SEEK_SET"/>
<attr name="TMP_MAX"/>
<attr name="W_OK"/>
<attr name="X_OK"/>
<elem name="os._AddedDllDirectory">
<attr name="close"/>
</elem>
<elem name="os._Environ">
<attr name="_MutableMapping__marker"/>
<attr name="_abc_impl"/>
<attr name="clear"/>
<attr name="copy"/>
<attr name="get"/>
<attr name="items"/>
<attr name="keys"/>
<attr name="pop"/>
<attr name="popitem"/>
<attr name="setdefault"/>
<attr name="update"/>
<attr name="values"/>
</elem>
<attr name="_check_methods"/>
<attr name="_execvpe"/>
<attr name="_exists"/>
<attr name="_exit"/>
<attr name="_fspath"/>
<attr name="_get_exports_list"/>
<attr name="_walk"/>
<elem name="os._wrap_close">
<attr name="close"/>
</elem>
<attr name="abc"/>
<attr name="abort"/>
<attr name="access"/>
<attr name="add_dll_directory"/>
<attr name="altsep"/>
<attr name="chdir"/>
<attr name="chmod"/>
<attr name="close"/>
<attr name="closerange"/>
<attr name="cpu_count"/>
<attr name="curdir"/>
<attr name="defpath"/>
<attr name="device_encoding"/>
<attr name="devnull"/>
<attr name="dup"/>
<attr name="dup2"/>
<attr name="environ"/>
<elem name="os.OSError">
<attr name="args"/>
<attr name="characters_written"/>
<attr name="errno"/>
<attr name="filename"/>
<attr name="filename2"/>
<attr name="strerror"/>
<attr name="winerror"/>
<attr name="with_traceback"/>
</elem>
<attr name="execl"/>
<attr name="execle"/>
<attr name="execlp"/>
<attr name="execlpe"/>
<attr name="execv"/>
<attr name="execve"/>
<attr name="execvp"/>
<attr name="execvpe"/>
<attr name="extsep"/>
<attr name="fdopen"/>
<attr name="fsdecode"/>
<attr name="fsencode"/>
<attr name="fspath"/>
<attr name="fstat"/>
<attr name="fsync"/>
<attr name="ftruncate"/>
<attr name="get_exec_path"/>
<attr name="get_handle_inheritable"/>
<attr name="get_inheritable"/>
<attr name="get_terminal_size"/>
<attr name="getcwd"/>
<attr name="getcwdb"/>
<attr name="getenv"/>
<attr name="getlogin"/>
<attr name="getpid"/>
<attr name="getppid"/>
<attr name="isatty"/>
<attr name="kill"/>
<attr name="linesep"/>
<attr name="link"/>
<attr name="listdir"/>
<attr name="lseek"/>
<attr name="lstat"/>
<attr name="makedirs"/>
<attr name="mkdir"/>
<attr name="name"/>
<attr name="open"/>
<attr name="pardir"/>
<attr name="path"/>
<attr name="pathsep"/>
<attr name="pipe"/>
<attr name="popen"/>
<attr name="putenv"/>
<attr name="read"/>
<attr name="readlink"/>
<attr name="remove"/>
<attr name="removedirs"/>
<attr name="rename"/>
<attr name="renames"/>
<attr name="replace"/>
<attr name="rmdir"/>
<attr name="scandir"/>
<attr name="sep"/>
<attr name="set_handle_inheritable"/>
<attr name="set_inheritable"/>
<attr name="spawnl"/>
<attr name="spawnle"/>
<attr name="spawnv"/>
<attr name="spawnve"/>
<attr name="st"/>
<attr name="startfile"/>
<attr name="stat"/>
<elem name="os.stat_result">
<attr name="count"/>
<attr name="index"/>
<attr name="n_fields"/>
<attr name="n_sequence_fields"/>
<attr name="n_unnamed_fields"/>
<attr name="st_atime"/>
<attr name="st_atime_ns"/>
<attr name="st_ctime"/>
<attr name="st_ctime_ns"/>
<attr name="st_dev"/>
<attr name="st_file_attributes"/>
<attr name="st_gid"/>
<attr name="st_ino"/>
<attr name="st_mode"/>
<attr name="st_mtime"/>
<attr name="st_mtime_ns"/>
<attr name="st_nlink"/>
<attr name="st_reparse_tag"/>
<attr name="st_size"/>
<attr name="st_uid"/>
</elem>
<elem name="os.statvfs_result">
<attr name="count"/>
<attr name="f_bavail"/>
<attr name="f_bfree"/>
<attr name="f_blocks"/>
<attr name="f_bsize"/>
<attr name="f_favail"/>
<attr name="f_ffree"/>
<attr name="f_files"/>
<attr name="f_flag"/>
<attr name="f_frsize"/>
<attr name="f_fsid"/>
<attr name="f_namemax"/>
<attr name="index"/>
<attr name="n_fields"/>
<attr name="n_sequence_fields"/>
<attr name="n_unnamed_fields"/>
</elem>
<attr name="strerror"/>
<attr name="supports_bytes_environ"/>
<attr name="supports_dir_fd"/>
<attr name="supports_effective_ids"/>
<attr name="supports_fd"/>
<attr name="supports_follow_symlinks"/>
<attr name="symlink"/>
<attr name="sys"/>
<attr name="system"/>
<elem name="os.terminal_size">
<attr name="columns"/>
<attr name="count"/>
<attr name="index"/>
<attr name="lines"/>
<attr name="n_fields"/>
<attr name="n_sequence_fields"/>
<attr name="n_unnamed_fields"/>
</elem>
<attr name="times"/>
<elem name="os.times_result">
<attr name="children_system"/>
<attr name="children_user"/>
<attr name="count"/>
<attr name="elapsed"/>
<attr name="index"/>
<attr name="n_fields"/>
<attr name="n_sequence_fields"/>
<attr name="n_unnamed_fields"/>
<attr name="system"/>
<attr name="user"/>
</elem>
<attr name="truncate"/>
<attr name="umask"/>
<elem name="os.uname_result">
<attr name="count"/>
<attr name="index"/>
<attr name="machine"/>
<attr name="n_fields"/>
<attr name="n_sequence_fields"/>
<attr name="n_unnamed_fields"/>
<attr name="nodename"/>
<attr name="release"/>
<attr name="sysname"/>
<attr name="version"/>
</elem>
<attr name="unlink"/>
<attr name="unsetenv"/>
<attr name="urandom"/>
<attr name="utime"/>
<attr name="waitpid"/>
<attr name="waitstatus_to_exitcode"/>
<attr name="walk"/>
<attr name="write"/>
</elem>
但是似乎没有深度超过 1 的嵌套类,所以我不确定我的代码是否正常工作,但代码不会在这里抛出错误。
但是treeobj(PyQt6.QtCore) 抛出错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in treeobj
File "<stdin>", line 9, in treeobj
File "<stdin>", line 7, in treeobj
AttributeError: 'TimerInfo' object attribute 'interval' is an instance attribute
如何修复我的代码?
getattr()函数访问PyQt6.QtCore.QAbstractEventDispatcher.TimerInfo对象的interval属性应该会报错,这是一个实例属性,getattr()不支持,所以报错。
什么是实例属性以及如何获取“普通属性”和实例属性的值?
【问题讨论】:
-
不要使用 eval,使用
*attr()函数进行对象属性操作,使用literal_eval()进行代码/结构评估。 -
提供具体的 Python 代码来构建生成 XML 输出的对象会更有用;我可以告诉你nested class 将提供你想要的
.表示法(通过__qualname__)。
标签: python python-3.x