2016-12-30 6 views
1

У меня есть этот 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" } ]} 

Этот файл читается этим питон сценария:

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') 

На данный момент я могу только напечатать только одно значение порта и идентификатор значение на выходе:

{ 
    "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 я смог добиться только чтения одного из значений порта, но я не знаю, как добиться, чтобы он печатал все значения порта для каждого идентификатора процесса.

Например:

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

Так значения PORT будет автоматически изменяться в случае модификаций JSon файла. Надеюсь, на этот раз я объяснил более четко.

+0

Если процесс имеет несколько портов, они всегда будут отображаться * последовательно в данных json? – wwii

+0

@ user54, проверка моего ответа, поскольку он явно удовлетворяет вашим критериям – penta

ответ

1

Ваш оригинальный код бросил исключение KeyError, когда ключ '{#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'}]} 
>>> 

Использование регулярных выражений.Я использую regex module, потому что это экономит повторные снимки, которые необходимы для процессов с несколькими портами

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'}]} 
>>> 
+0

Я получаю нулевые значения везде :('{# PROC_PORT_1111}' был просто пробной версией для печати порта 1111. Но мне нужно как-то в порядке сценария автоматически определить '{#PROC_PORT_PORT_NUMBER_HERE}', например, если у нас есть порт 2025 и 1701 для proc test1 - это будет «{#ID}»: «test1», «{# PORT_2025}»: «2025», «{# PORT_1701}»: «1701». И так далее для остальных pocess_ids, как показано на последнем выходе из моего запроса. Порты могут быть совершенно разными, и их сумма может быть и другой. – user54

+0

@ user54 - Я не понял ваш комментарий. Я отредактировал ответ - посмотрим, что это за то, что вам нужно. Использует ли ваш пример данные json действительно представляют фактические данные? - Если нет, предоставьте небольшую часть фактических данных json в своем вопросе. – wwii

+0

@ user54, какую версию Python вы используете? – wwii

1

Вам необходимо обновить {#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, а не [], поскольку прежний никогда не выбрасывает KeyError, тогда как последний делает это.

Ресурс: dict.get

+0

Извините, но это не сработает. Он печатает мне нулевые значения для #PROC_PORT, и мне нужен не только PROC_PORT_1111. Мне нужны и другие порты, как показано на последнем выходе json. – user54

+0

Я отредактировал свой ответ, чтобы предоставить правильное решение. Проблема заключалась в том, что вы всегда получали значение для # PROC_PORT_1111 на каждой итерации цикла, а не увеличивали его до 2222, 3333 и т. Д. –

+0

Спасибо за усилия, но, к сожалению, это не имеет смысла, пока значения порта могут быть другой. Например: 89, 2001 и т. Д. И, таким образом, в случае таких изменений код не будет динамичным, если каждый раз потребуется исправление. – user54

1

Насколько мне известно, я понял, что ваше поле "{#PROC_PORT_2222}" изменения с числами, т.е. "{#PROC_PORT_XXXX}" так что в этом case нам нужно использовать регулярное выражение для соответствия любой строке, которая имеет "{#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 это TXT файл, имеющий JSON.

Это дает выход.

1111 
3333 
2222 
4444 

P.S. Если вы имели в виду имя ключа просто PORT не PROC_PORT, а затем заменить строку

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

по regex = r"{#PORT_[0-9]{4}}"

PPS Я предположил, что цифры, которые будут меняться будет 4 цифры, если нет, то просьба прокомментировать ниже

+0

Будет ли ваше решение * строить * OP желаемый результат? – wwii

+0

yes it it, попробуйте сами :-) – penta

+0

@wwii кто OP? – penta

Смежные вопросы