записывать данные в файл JSON при многопроцессорной обработке с использованием Python - PullRequest
0 голосов
/ 13 марта 2019

Я новичок в питоне.Я пишу программу на Python для записи в файл JSON, если веб-сайт недоступен.Несколько веб-сайтов будут храниться в переменной hosts.Это будет проверяться каждые 5 секунд.Я использовал пул из многопроцессорной обработки для одновременной обработки веб-сайта.После этого я запишу данные в файл json.Но здесь он записывает только один веб-сайт в файл JSON.Итак, как сделать так, чтобы записать две данные одновременно.

Вот пример кода:

import os
from multiprocessing import Pool
from datetime import datetime
import time
import json

hosts = ["www.google.com","www.smackcoders.com"]
n = len(hosts)

def write(hosts):
    u = "down"
    name = "stack.json"
    if not os.path.exists(name):
        with open(name, 'w') as f:
            f.write('{}')
    result = [(timestamp, {'monitor.status': u,
                           "monitor.id": "tcp-tcp@"+hosts
                           })]

    with open(name, 'rb+') as f:
        f.seek(-1, os.SEEK_END)
        f.truncate()
        for entry in result:
            _entry = '"{}":{},\n'.format(entry[0], json.dumps(entry[1]))
            _entry = _entry.encode()
            f.write(_entry)
        f.write('}'.encode('ascii'))

def main(hosts):
    p = Pool(processes= n)
    result = p.map(write, hosts)
while True:
    timestamp = datetime.now().strftime("%B %d %Y, %H:%M:%S")
    main(hosts)
    time.sleep(5)

Мой вывод:

""March 13 2019, 10:49:03":{"monitor.id": "tcp-tcp@www.smackcoders.com", "monitor.status": "down"},
}

Требуемый вывод:

{"March 13 2019, 10:49:03":{"monitor.id": "tcp-tcp@www.smackcoders.com", "monitor.status": "down"},"March 13 2019, 10:49:03":{"monitor.id": "tcp-tcp@www.google.com", "monitor.status": "down"},
}

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Вот другой вариант, который будет использовать Thread over Pool.

Создан класс для получения возврата из join ()

# Class that overwrite Thread to get the return of join()
class ThreadWithReturnValue(Thread):
    def __init__(self, group=None, target=None, name=None, args=None, kwargs=None, Verbose=None):
        if args is None:
            args = ()
        if kwargs is None:
            kwargs = {}

        super().__init__(group, target, name, args, kwargs)
        self._return = None

    def run(self):
        print(type(self._target))
        if self._target is not None:
            self._return = self._target(*self._args, **self._kwargs)

    def join(self, *args):
        Thread.join(self, *args)
        return self._return

Я изменил код, чтобы сначала получить статус каждого хоста, а затем записать результат в ваш файл. Также исправлен способ написания файла JSON.

import os
from datetime import datetime
import time
import json
from threading import Thread

hosts = ["www.google.com","www.smackcoders.com"]
filepath = os.path.join(os.getcwd(), "stack.json")
n = len(hosts)


def perform_ping(host_ip):
    """
    You have hardcoded down, this method will ping to check if we get an ICMP response
    """
    response = os.system("ping -c 1 " + host_ip)
    if response == 0:
        return 'UP'
    else:
        return 'DOWN'


def write_result(timestamp, results):
    # u = "down"  Using perform_ping to get the status

    if not os.path.exists(filepath):
        current_file = {}
    else:
       # If file exist, reading the current output
        with open(filepath, 'r') as f_read:
            current_file = json.loads(f_read.read())

    inner_result = []
    for result in results:
        host, status = result
        inner_result.append({'monitor.status': status,
                             "monitor.id": "tcp-tcp@"+host
                    })

    current_file[timestamp] = inner_result

    # writing the file with new input
    with open(filepath, 'w') as f_write:
        f_write.write(json.dumps(current_file))


def main():
    while True:
        thread_list = []
        for host_ip in hosts:
            thread_list.append(ThreadWithReturnValue(target=perform_ping, name=host_ip, args=(host_ip, )))
        results = []
        timestamp = datetime.now().strftime("%B %d %Y, %H:%M:%S")
        for thread in thread_list:
            thread.start()
        for thread in thread_list:
            results.append((thread.name, thread.join()))
        # Ping is done in parallel, writing the result at the end to avoid thread collision and reading/writing the file to many times if you increase the number of host
        write_result(timestamp, results)
        time.sleep(5)


if __name__ == '__main__':
    main()
0 голосов
/ 13 марта 2019

Я внес небольшие изменения в ваш код и реализовал блокировку.

import os
from multiprocessing import Pool,RLock
from datetime import datetime
import time
import json

file_lock=RLock()
hosts = ["www.google.com","www.smackcoders.com"]
n = len(hosts)

def write(hosts):
    u = "down"
    name = "stack.json"
    if not os.path.exists(name):
        with open(name, 'w') as f:
            f.write('{}')
    result = [(timestamp, {'monitor.status': u,
                           "monitor.id": "tcp-tcp@"+hosts
                           })]
    with file_lock:
        with open(name, 'rb+') as f:
            f.seek(-1, os.SEEK_END)
            f.truncate()
            for entry in result:
                _entry = '"{}":{},\n'.format(entry[0], json.dumps(entry[1]))
                _entry = _entry.encode()
                f.write(_entry)
            f.write('}'.encode('ascii'))


def main(hosts):
    p = Pool(processes= n)
    result = p.map(write, hosts)
while True:
    timestamp = datetime.now().strftime("%B %d %Y, %H:%M:%S")
    main(hosts)
    time.sleep(5)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...