多个Python线程写入单个JSON文件

时间:2017-06-14 01:37:31

标签: python json multithreading

我正在调整this project(下面扩展)中的Python脚本,以便更新JSON文件的元素,而不是InitialState流。但是,由于脚本打开了多个线程,因此无法将每个线程的数据简洁地写回文件,因为它将同时读取,更改并写回所有线程中的文件。因为只能有一个文件,所以没有版本会准确,因为最后一个线程会覆盖所有其他文件。

问题:如何在不影响其他线程的写入操作或锁定文件的情况下(同时)更新基于每个线程的JSON中的状态?

JSON文件包含我想用python脚本操作的占用者状态:

{
 "janeHome": "false",
 "johnHome": "false",
 "jennyHome": "false",
 "jamesHome": "false"
}

这是python脚本:

import subprocess
import json
from time import sleep
from threading import Thread

# Edit these for how many people/devices you want to track
occupant = ["Jane","John","Jenny","James"]

# MAC addresses for our phones
address = ["11:22:33:44:55:66","77:88:99:00:11:22","33:44:55:66:77:88","99:00:11:22:33:44"]

# Sleep once right when this script is called to give the Pi enough time
# to connect to the network
sleep(60)

# Some arrays to help minimize streaming and account for devices
# disappearing from the network when asleep
firstRun = [1] * len(occupant)
presentSent = [0] * len(occupant)
notPresentSent = [0] * len(occupant)
counter = [0] * len(occupant)

# Function that checks for device presence
def whosHere(i):

    # 30 second pause to allow main thread to finish arp-scan and populate output
    sleep(30)

    # Loop through checking for devices and counting if they're not present
    while True:

        # Exits thread if Keyboard Interrupt occurs
        if stop == True:
            print ("Exiting Thread")
            exit()
        else:
            pass

        # If a listed device address is present print
        if address[i] in output:
            print(occupant[i] + "'s device is connected")
            if presentSent[i] == 0:

                # TODO: UPDATE THIS OCCUPANT'S STATUS TO TRUE

                # Reset counters so another stream isn't sent if the device
                # is still present
                firstRun[i] = 0
                presentSent[i] = 1
                notPresentSent[i] = 0
                counter[i] = 0
                sleep(900)
            else:
                # If a stream's already been sent, just wait for 15 minutes
                counter[i] = 0
                sleep(900)
        # If a listed device address is not present, print and stream
        else:
            print(occupant[i] + "'s device is not connected")
            # Only consider a device offline if it's counter has reached 30
            # This is the same as 15 minutes passing
            if counter[i] == 30 or firstRun[i] == 1:
                firstRun[i] = 0
                if notPresentSent[i] == 0:

                    # TODO: UPDATE THIS OCCUPANT'S STATUS TO FALSE

                    # Reset counters so another stream isn't sent if the device
                    # is still present
                    notPresentSent[i] = 1
                    presentSent[i] = 0
                    counter[i] = 0
                else:
                    # If a stream's already been sent, wait 30 seconds
                    counter[i] = 0
                    sleep(30)
            # Count how many 30 second intervals have happened since the device 
            # disappeared from the network
            else:
                counter[i] = counter[i] + 1
                print(occupant[i] + "'s counter at " + str(counter[i]))
                sleep(30)

# Main thread
try:

    # Initialize a variable to trigger threads to exit when True
    global stop
    stop = False

    # Start the thread(s)
    # It will start as many threads as there are values in the occupant array
    for i in range(len(occupant)):
        t = Thread(target=whosHere, args=(i,))
        t.start()

    while True:
        # Make output global so the threads can see it
        global output

        # Reads existing JSON file into buffer
        with open("data.json", "r") as jsonFile:
            data = json.load(jsonFile)
            jsonFile.close()

        # Assign list of devices on the network to "output"
        output = subprocess.check_output("arp-scan -interface en1 --localnet -l", shell=True)

        temp = data["janeHome"]
        data["janeHome"] = # RETURNED STATE
        data["johnHome"] = # RETURNED STATE
        data["jennyHome"] = # RETURNED STATE
        data["jamesHome"] = # RETURNED STATE

        with open("data.json", "w") as jsonFile:
            json.dump(data, jsonFile)
            jsonFile.close()

        # Wait 30 seconds between scans
            sleep(30)

except KeyboardInterrupt:
    # On a keyboard interrupt signal threads to exit
    stop = True
    exit()

我认为我们都同意最好的想法是将数据从每个线程返回到main并在一个位置将其写入文件,但这里是令人困惑的地方,每个线程检查一个不同的人,如何将国家传回主要的写作?

0 个答案:

没有答案