打印所有端口值

时间:2016-12-30 16:40:02

标签: python json

我有这个json文件:

{ "data":  [    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test1", "{#PROC_ARGS}": "-l -c -g -k /etc/test1.conf", "{#PROC_PORT_1111}": "1111", "{#PROC_CONF}": "/etc/test1.conf" },    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test2", "{#PROC_ARGS}": "-l -c -g -k /etc/test2.conf", "{#PROC_PORT_2222}": "2222", "{#PROC_PORT_3333}": "3333", "{#PROC_CONF}": "/etc/test2.conf" },    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test3", "{#PROC_ARGS}": "-l -c -g -k /etc/test3.conf", "{#PROC_PORT_4444}": "4444", "{#PROC_CONF}": "/etc/test3.conf" }  ]}

此python脚本正在读取此文件:

import json
import re
import sys
import unittest
import StringIO

def TestPorts(discoveryJson, spJson):
    jsn = json.load(discoveryJson)
    for dt in jsn['data']:
        try:
            id = dt['{#PROC_IDENT}']
            port = dt['{#PROC_PORT_1111}']
            spJson['data'].append({'{ID}': id, '{#PORT_1111}': port})
        except Exception as err:
            pass

def printTestPort(discFilespec, dumpDest=sys.stdout):
    portJson = {'data': []}
    try:
        with open(discFilespec) as discJson:
            TestPorts(discJson, portJson)
    except:
        pass
    json.dump(portJson, dumpDest)

if __name__ == '__main__':
    printTestPort('/tmp/file.json')

目前我只能在输出中打印一个端口值和id值:

{
    "data": [
        {
            "{#ID}": "test1",
            "{#PORT_1111}": "1111"
        }
    ]
}

如何获得下一个输出? :

{
        "data": [
            {
                "{#ID}": "test1",
                "{#PORT_1111}": "1111"
            },
            {
                "{#ID}": "test2",
                "{#PORT_2222}": "2222",
                "{#PORT_3333}": "3333"
            },
            {
                "{#ID}": "test3",
                "{#PORT_4444}": "4444"
            }
        ]
    }

你能帮忙实现它吗?

让我再说一遍。

此json文件可能会更改为端口值:

{ "data":  [    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test1", "{#PROC_ARGS}": "-l -c -g -k /etc/test1.conf", "{#PROC_PORT_1111}": "1111", "{#PROC_CONF}": "/etc/test1.conf" },    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test2", "{#PROC_ARGS}": "-l -c -g -k /etc/test2.conf", "{#PROC_PORT_2222}": "2222", "{#PROC_PORT_3333}": "3333", "{#PROC_CONF}": "/etc/test2.conf" },    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test3", "{#PROC_ARGS}": "-l -c -g -k /etc/test3.conf", "{#PROC_PORT_4444}": "4444", "{#PROC_CONF}": "/etc/test3.conf" }  ]}

因此,每个流程实例可能具有不同数量的具有不同值的端口。例如,test1可能有1237 7000和1234端口值test2仅9004,依此类推。

在我的python代码中,我只能读取一个端口值,但我不知道如何实现,以便按进程id打印所有端口值。

例如:

{
        "data": [
            {
                "{#ID}": "test1",
                "{#PORT_1205}": "1205"
            },
            {
                "{#ID}": "test2",
                "{#PORT_442}": "442",
                "{#PORT_2004}": "2004"
            },
            {
                "{#ID}": "test3",
                "{#PORT_4444}": "9001"
            }
        ]
    }

因此,如果修改了json文件,PORT值将自动更改。希望这次我能更清楚地解释一下。

3 个答案:

答案 0 :(得分:1)

您需要更新循环中的{#PROC_PORT_1111}密钥,以便在每次迭代时获取下一个端口(222233334444等。我添加了一个incr变量来跟踪它。还要编辑您的函数,以便在访问字典时使用get

def TestPorts(discoveryJson, spJson):
    jsn = json.load(discoveryJson)
    incr = 1111;
    for dt in jsn.get('data'):
        try:
            id = dt.get('{#PROC_IDENT}')
            port = dt.get('{#PROC_PORT_' + str(incr) + '}')
            spJson.get('data').append({'{ID}': id, '{#PORT_' + str(incr) + '}': port})
            incr += incr;
        except Exception as err:
            pass

如果您在print分支中添加except语句,您会注意到由于KeyError,您的执行将会触发该分支两次。使用get而不是[]通常是一种更好的做法,因为前者从不抛出KeyError而后者则抛出this

资源:dict.get

答案 1 :(得分:1)

当密钥{ "command": "extension.sayHello", "title": "Say Hello", "context": { "where": "explorer/context", "when": "json" } } 不存在时,您的原始代码抛出了KeyError,因此您无法捕获其他端口。这是一种方法 - 迭代项目;检查您是否对该项目感兴趣;按摩它;将它放在一个新容器中。

'{#PROC_PORT_1111}'

使用正则表达式。我正在使用regex module,因为它可以保存带有多个端口的进程所需的重复捕获

#setup
import json, io
from pprint import pprint
s = """{ "data":  [    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test1", "{#PROC_ARGS}": "-l -c -g -k /etc/test1.conf", "{#PROC_PORT_1111}": "1111", "{#PROC_CONF}": "/etc/test1.conf" },    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test2", "{#PROC_ARGS}": "-l -c -g -k /etc/test2.conf", "{#PROC_PORT_2222}": "2222", "{#PROC_PORT_3333}": "3333", "{#PROC_CONF}": "/etc/test2.conf" },    { "{#PROC}": "/usr/local/test", "{#PROC_IDENT}": "test3", "{#PROC_ARGS}": "-l -c -g -k /etc/test3.conf", "{#PROC_PORT_4444}": "4444", "{#PROC_CONF}": "/etc/test3.conf" }  ]}"""
f = io.StringIO(s)

j = json.load(f)
new_j = {'data' : []}
for d in j['data']:
    new_d = {}
    new_d['{#ID}'] = d['{#PROC_IDENT}']
    for k, v in d.items():
        if k.startswith('{#PROC_PORT'):
            k = k.replace('PROC_', '')
            new_d[k] = v
    new_j['data'].append(new_d)


>>> pprint(new_j)

{'data': [{'{#ID}': 'test1', '{#PORT_1111}': '1111'},
          {'{#ID}': 'test2', '{#PORT_2222}': '2222', '{#PORT_3333}': '3333'},
          {'{#ID}': 'test3', '{#PORT_4444}': '4444'}]}
>>>

答案 2 :(得分:1)

据我所知,我了解您的字段"{#PROC_PORT_2222}"会随着数字而变化,即"{#PROC_PORT_XXXX}"所以在这种情况下,我们需要使用正则表达式来匹配任何具有"{#PROC_PORT_}"的字符串为固定字符串

import re
import json

with open('s.txt') as data_file:
    data = json.load(data_file)

k = data['data']
regex = r"{#PROC_PORT_[0-9]{4}}"

test_str = str(k)
lst=[]
matches = re.finditer(regex, test_str)
for matchNum, match in enumerate(matches):
    matchNum = matchNum + 1
    lst.append("{match}".format(match=match.group()))


for b in k:
    for a in lst:
        try:
            print b[str(a)]
        except:
            pass

s.txt是具有json的txt文件。

这给出了输出。

1111
3333
2222
4444

<强> P.S。如果您的意思是密钥名称只是PORT而不是PROC_PORT ,那么请替换

regex = r"{#PROC_PORT_[0-9]{4}}"

通过  regex = r"{#PORT_[0-9]{4}}"

P.P.S我认为将改变的数字将是4位数,如果没有,那么请在下面评论