【问题标题】:Create name value pairs in python在 python 中创建名称值对
【发布时间】:2013-10-01 12:44:46
【问题描述】:

我有一个 python 脚本,它的以下输出存储在一个名为 jvmData 的变量中:

Stats name=jvmRuntimeModule, type=jvmRuntimeModule#
{
name=HeapSize, ID=1, description=The total memory (in KBytes) in the Java virtual machine run time., unit=KILOBYTE, type=BoundedRangeStatistic, lowWaterMark=1048576, highWaterMark=1048576, current=1048576, integral=0.0, lowerBound=1048576, upperBound=2097152

name=FreeMemory, ID=2, description=The free memory (in KBytes) in the Java virtual machine run time., unit=KILOBYTE, type=CountStatistic, count=348466

name=UsedMemory, ID=3, description=The amount of used memory (in KBytes) in the Java virtual machine run time., unit=KILOBYTE, type=CountStatistic, count=700109

name=UpTime, ID=4, description=The amount of time (in seconds) that the Java virtual machine has been running., unit=SECOND, type=CountStatistic, count=3706565

name=ProcessCpuUsage, ID=5, description=The CPU Usage (in percent) of the Java virtual machine., unit=N/A, type=CountStatistic, count=0
}

我想做的只是打印出重要部分的名称/值对,在这种情况下就是:

HeapSize=1048576
FreeMemory=348466
UsedMemory=700109
UpTime=3706565
ProcessCpuUsage=0

我对 python 一点也不擅长 :) 我脑子里唯一的解决方案似乎很啰嗦?拆分行,丢弃第一行、第二行和最后一行,然后以不同的情况(有时是当前的,有时是计数的)循环遍历每一行以查找字符串的长度等

也许(当然)我错过了一些不错的功能,我可以使用这些功能将它们放入相当于 java hashmap 之类的东西中?

【问题讨论】:

    标签: python string parsing


    【解决方案1】:

    “java HashMap 的等价物”在 python 中被称为字典。至于如何解析这个,只需遍历包含数据的行,对行中的所有键/值对进行字典,并为HeapSize 提供特殊情况:

    jvmData = "..." #the string holding the data
    jvmLines = jvmData.split("\n") #a list of the lines in the string
    lines = [l.strip() for l in jvmLines if "name=" in l] #filter all data lines
    result = {}
    for line in lines:
        data = dict(s.split("=") for s in line.split(", "))
        #the value is in "current" for HeapSize or in "count" otherwise
        value = data["current"] if data["name"] == "HeapSize" else data["count"]
        result[data["name"]] = value
    

    由于您似乎被困在 Jython2.1 上,这里有一个可以使用它的版本(显然未经测试)。与上面基本相同,但列表推导和生成器表达式分别替换为filtermap,并且没有使用三元if/else 运算符:

    jvmData = "..." #the string holding the data
    jvmLines = jvmData.split("\n") #a list of the lines in the string
    lines = filter(lambda x: "name=" in x, jvmLines) #filter all data lines
    result = {}
    for line in lines:
        data = dict(map(lambda x: x.split("="), line.split(", ")))
        if data["name"] == "HeapSize":
            result[data["name"]] = data["current"]
        else:
            result[data["name"]] = data["count"]
    

    【讨论】:

    • 感谢@l4mpi 的有用回答
    • hmm,我将字符串保存在一个名为 jvmData 的变量(不是文件)中,并尝试相应地更改您的代码。即'lines = [l.strip() for l in jvmData if "name=" in l]' 但语法错误 -> lines = lstrip()^for l in jvmData if "name=" in l
    • 您的错误消息中缺少列表理解的 [] 括号,您可能在更改期间删除了这些括号。为了使列表理解起作用,您还需要将字符串拆分为行。请参阅我的编辑以获取应该可行的解决方案。
    • 仍然得到相同的结果... - 这是完整的输出(指针指向 'for' 中的 'f')
    • WASX7017E: 运行文件“/tmp/test.py”时收到异常;异常信息:com.ibm.bsf.BSFException:来自 Jython 的异常:Traceback(最里面的最后一个):(无代码对象)第 0 行文件“”,第 28 行 data = dict(s.split("=") for s in line.split(", ")) ^ SyntaxError: invalid syntax
    【解决方案2】:

    尝试使用 find 函数和小 re:

    import re
    final_map = {}
    NAME= 'name='
    COUNT= 'count='
    HIGHWATERMARK= "highWaterMark="
    def main():    
        with open(r'<file_location>','r') as file:
            lines = [line for line in file if re.search(r'^name', line)]        
            for line in lines:                    
                sub = COUNT if line.find(COUNT) != -1  else HIGHWATERMARK       
                final_map[line[line.find(NAME)+5:line.find(',')]] = line[line.find(sub)+len(sub):].split(',')[0].strip()
                print line[line.find(NAME)+5:line.find(',')]+'='+final_map[line[line.find(NAME)+5:line.find(',')]]                
    
    if __name__ == '__main__':
        main()
    

    输出:

    HeapSize=1048576
    FreeMemory=348466
    UsedMemory=700109
    UpTime=3706565
    ProcessCpuUsage=0
    

    【讨论】:

    • 这就是我喜欢这个地方的原因 - 一个问题和不同的方法回来看起来都一样好:) 我也会尝试你的方法,我会更新问题以指定我有数据变量而不是文件
    • 投反对票。在我看来,正则表达式并不是解决这个问题的最佳工具,但这段代码是一个特别糟糕的例子。您在列表理解中不必要地使用 re.search 而不是 in 运算符;更糟糕的是,您通过对find 结果加上字符串长度进行切片来获取值,这是违反直觉的并且容易中断(替换搜索字符串并忘记更改 int,您会默默地得到错误的结果) - re.match 带有捕获组会更好。但是,当您可以使用简单的 split 将整行转换为字典时,为什么还要使用 re
    • @l4mpi :因为您已经介绍了 dict 方式。我想用不同的方式来写它。同时,当我首先编写代码时,他没有指定这些值是可变的。只要文件是静态的,在切片中查找就可以很好地工作。搜索特定事物比加载地图中的所有内容更有效,就像您的情况一样,如果输入大小不断增长,这将非常麻烦。
    • 好吧,请随意提出替代解决方案,但请以不提倡不良做法的方式提出。说真的,在代码中获取名称和值的方式很糟糕。最糟糕的例子是highWaterMark 行,您可以在其中计算line[line.find('highWaterMark=')+14:][:line[line.find('highWaterMark=')+14:].find(',')].strip(),它几乎在我能想象的所有方面都失败了。对于初学者,您可以将其表示为line.split("highWaterMark=")[1].split(",")[0]。使用splitre.match 可以替代我的解决方案,您当前的代码肯定不是。
    • 切片总是比分割更有效。为什么这容易出错,以及切片到底是如何成为一种不好的做法?我了解您提出的建议是一个小解决方案,但这绝对不是内存管理方面的最佳解决方案。 Split 将创建两个不可变的字符串内存块,而 slice 只是指向 256 整数寄存器的已可用整数的指针/引用。
    猜你喜欢
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    相关资源
    最近更新 更多