首页 > 解决方案 > 解析具有变量值的数据

问题描述

我在当前项目中遇到了一个令人困惑的问题。基本上,我正在逐字节分析 MIDI 文件(是的,我必须这样做)。MIDI 文件的结构使得轨道中任何给定事件的数据通过称为“消息”的一系列字节来传送。MIDI 设备根据状态代码知道什么类型的消息,状态代码是“消息”中的 1-3 个字节,具有特定功能的特定 ID。

我需要能够查看 MIDI 文件的数据并将每个“消息”记录为一个独立的对象,以便我可以将它们按顺序排列以备后用。我遇到的问题是,当我处理数据时,我需要一种有效的方法来读取每个状态代码并将其与我编写的用于处理该类型消息的数据的函数相匹配。我现在要做的是:

首先,在整个 MIDI 文件中的任何给定点,我查看接下来的 3 个字节并将它们与我的所有可能的 3 字节 MIDI 状态代码列表进行比较。这是我的第一个问题。对于所有 3 字节的状态码(相当于6 个十六进制数字,这是 MIDI 编辑中经常使用的编码),第 5-8 位(也就是第二个十六进制数字)指定当前消息影响的 MIDI 通道,这是可变的和不可预测的。由于无法预测通道,因此需要将其视为通配符值。换句话说,当我在我的代码列表中引用它时,我需要以某种方式获取 6 位数字并忽略第 2 位。我不认为我解释得很好,所以这里有一个例子:

文件内的6个十六进制数字代码:通道号Bn7800在哪里n

6位代码列表:['Bn7800','Bn7900','FF2001','FF2F00',...]

我需要在该列表中搜索正确的代码,同时忽略第二个数字,因为我无法提前知道它是什么。

我的另一个问题是,一旦有了该代码,我就需要调用我编写的处理该特定状态代码的特定函数。我已经在它们对应的状态码之后命名了所有函数,但问题是,我不知道如何获取我在上面列表中找到的字符串并使用它来调用函数。例如:

我需要:Bn7800 在列表中,我找到它!所以我将它存储为一个名为stat_code = 'Bn7800'. 但是我不能以这种方式调用我的函数->self.stat_code(data) 因为stat_code不是我想要的函数的名称。我想要以 . 的值命名的函数stat_code

我不确定如何根据存储变量的值调用函数。


抱歉,如果这令人困惑,如果不尝试解释整个 MIDI 文件结构,我很难完全解释。如果有不清楚的地方,请向我提问。谢谢!


编辑:这是一些代码:

self.event_status_codes = {'ff0002': ff_00_02,'ff01': ff_01,'ff02': ff_02,'ff03': ff03,'ff04': ff_04,'ff05': ff_05,'ff06': ff_06,'ff07': ff_07,'ff2001': ff_20_01,'ff2f00': ff_2f_00,'ff5103': ff_51_03,'ff5405': ff_54_05,'ff5804': ff_58_04,'ff5902': ff_59_02,'ff7f': ff_7f,'8n': _8n,'9n': _9n,'an': an,'bn': bn,'cn': cn,'dn': dn,'en': en,'bn7800': bn_78_00,'bn7900': bn_79_00,'bn7a': bn_7a,'bn7b00': bn_7b_00,'bn7c00': bn_7c_00,'bn7d00': bn7d00,'bn7e': bn_7e,'bn7f00': bn_7f_00,'f0': f0,'f7': f7}

    if track_data[hbc:hbc+3] in self.event_status_codes:  
        status_code = track_data[hbc:hbc+3]
        self.status_code(track_data)

作为参考,track_data我正在解析的原始十六进制序列hbc是一个简单的指针,它一次遍历文件一个十六进制数字。我发布了整个状态码字典,但现在主要关注 3 位数字,因为它们通常指定频道号。此外,从技术上讲,它是一个 Python 字典,因为我必须将每个对应的函数命名为与实际代码稍有不同的名称,以使其具有可读性和功能性,因此您可以忽略字典中每个键的值。

标签: pythonregexparsing

解决方案


我不确定如何根据存储变量的值调用函数。

这可以通过按名称引用函数来实现。在您的问题中,您暗示您正在调用函数 on self,这使得它更容易:您可以通过使用getattr()函数获取包含函数指针的属性,然后调用它:

stat_code = 'B67800'
func = getattr(self, f'function_name_{stat_code}')
value = func()
# do stuff with value

如果您的函数是任何其他模块的一部分,这也适用 - 只需self在该示例中替换为您从中调用它的模块的名称。

如果您需要调用全局定义的函数(不是模块的一部分),您可能需要索引locals()or globals()

func = globals()[f'function_name_{stat_code}']
value = func()

推荐阅读