Python 打印所有端口值

Python 打印所有端口值,python,json,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}":

我有这个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文件时自动更改。希望这次我解释得更清楚。

您需要更新循环中的
{PROC_PORT_1111}
键,以便它在每次迭代中都获得下一个端口(
2222
3333
4444
,等等)。我添加了一个
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
而不是
[]
通常是一种更好的做法,因为前者从不抛出
键错误,而后者则抛出


资源:

当密钥
'{PROC_PORT_1111}'不存在时,您的原始代码抛出了一个密钥错误,因此无法捕获其他端口。这里有一种方法——迭代项目;查看您是否对该项目感兴趣;按摩它;把它放在一个新的容器里

#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'}]}
>>>

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

import json
import regex
from pprint import pprint

pattern = r'{.*?(?P<id>"{#PROC_IDENT}"[^,]+).*?((?P<ports>"{#PROC_PORT_\d+}"[^,]+),\s?)+'
r = regex.compile(pattern)
# formatting string
new_json = """{{ "data": [{}  ]}}"""
items = []

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)
data = f.read()

#with open('s.txt') as f:
#    data = f.read()

for m in r.finditer(data):
    d = m.capturesdict()
    d['id'][0] = d['id'][0].replace('PROC_IDENT', 'ID')
    d['ports'] = [port.replace('PROC_', '') for port in d['ports']]
    s = ','.join(thing for v in d.values() for thing in v)
    items.append('{{{}}}'.format(s))

new_json = new_json.format(',    '.join(items))
j = json.loads(new_json)


>>> pprint(j)
{'data': [{'{#ID}': 'test1', '{#PORT_1111}': '1111'},
          {'{#ID}': 'test2', '{#PORT_2222}': '2222', '{#PORT_3333}': '3333'},
          {'{#ID}': 'test3', '{#PORT_4444}': '4444'}]}
>>>
导入json
导入正则表达式
从pprint导入pprint
pattern=r'{.*?(?P“{PROC#u IDENT}”[^,]+).*(?P“{PROC#u PORT\ud+}”[^,]+),\s?+'
r=regex.compile(模式)
#格式化字符串
new_json=“”{{“数据”:[{}]}”“”
项目=[]
“数据:”“““{”数据:“{”数据:“{”数据:“{”数据:“{”数据:“{”数据:“{”数据:“{”数据:““{”数据:“““{”数据:”““{”数据:““{”数据:“{”数据:“““{”数据:“{”数据:“{”数据:“{”数据:“{”数据:“““““““““{”数据”数据”数据:““““““““““,”””””””““““““““““{”数据”数据”数据:“““““““““::::::::::---l-l-l-l-l-l-l-l-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-c-g-g-g-g-g-g-g-"PROC#u ARGS":“-l-c-g-k/etc/test2.conf”、“{PROC#u PORT_2222}”:“2222”、“{PROC#u 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#port4444}”:“4444”,“{PROC#ARGS}”:“test3”;“{
f=io.StringIO(s)
data=f.read()
#将open('s.txt')作为f:
#data=f.read()
对于r.finditer中的m(数据):
d=m.capturesdict()
d['id'][0]=d['id'][0]。替换('PROC_IDENT','id')
d['ports']=[port.replace('PROC_','')用于d['ports']]中的端口
s=','.join(d中的v的thing.v中的thing的value())
items.append({{}}.format)
new_json=new_json.format(','.join(项目))
j=json.loads(新的_-json)
>>>pprint(j)
{'data':[{'ID}':'test1',{'PORT#u 1111}':'1111},
{{{ID}:'test2',{{PORT{2222}:'2222',{PORT{3333}:'3333},
{{{ID}:'test3',{{PORT}:'4444}]}
>>>

据我所知,我了解您的字段
“{code>随着数字的变化而变化,即
“{PROC#u PORT_XXXX}”
,因此在这种情况下,我们需要使用regex来匹配作为固定字符串的任何字符串

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.如果您的意思是密钥名称只是端口而不是进程端口,请替换该行

regex = r"{#PROC_PORT_[0-9]{4}}"
regex=r“{#端口{0-9]{4}”


p.p.S我假设将要更改的数字是4位数字,如果不是,请在下面发表评论

抱歉,但它不起作用。它为#PROC_端口打印空值,我不仅需要PROC_端口_1111。我还需要上一次json输出中显示的其他端口。我已经编辑了我的答案,以提供正确的解决方案问题是,在循环的每次迭代中,您总是得到#PROC_PORT_1111的值,而不是将其增加到2223333等。感谢您的努力,但不幸的是,只要端口值可能不同,它就没有意义。例如:89、2001等。因此,在这种情况下,只要每次我需要更正它。如果您在附加到spJson之前不知道端口值,您可以在之前读取一次该文件,以获取所有不同的端口值并将其填充到列表中。然后,您可以解析json,对于该列表中的每个端口值,获取其值,并附加到spJson。我在任何地方都会得到空值:('{#PROC#u PORT_1111}只是打印端口1111的一个尝试。但是我需要某种方式来让脚本自动确定{#PROC#u PORT_PORT_PORT_NUMBER_HERE}例如,如果我们有2025端口和1701用于PROC test1,它将“{#ID}”:“test1”,“{#PORT#u 2025}”:“2025”,“2025”,“1701”:“1701”"。等等。对于其余的pocess_ID,如我请求的最后一个输出中所示。端口可能完全不同,它们的数量也可能不同。@user54-我不理解您的评论。我编辑了答案-看看这是否是您想要的。您的示例json数据真的代表了实际数据吗?-如果不是,请e在您的问题中提供一小部分实际的json数据。@user54您使用的是哪一版本的Python?您的解决方案是否会构造OP所需的结果?@wwii谁是OP?原始PosterIf一个进程有多个端口,它们是否总是按顺序显示在json数据中?@user54,请检查我的答案,因为它显然满足您的标准ia