Python 这是一种共享动态ConfigObj文件的体面方式吗?

Python 这是一种共享动态ConfigObj文件的体面方式吗?,python,python-multithreading,configobj,Python,Python Multithreading,Configobj,我有几个python进程,它们监视物理IO并对其进行操作。例如,如果电流过高,则关闭电机。他们需要让对方知道他们为什么要做某事,所以我认为共享文件可能是一个简单的解决方案。各种进程都可以写入该文件,其他进程需要知道该文件何时被写入。我已经将ConfigObj用于静态配置文件,所以我想尝试一下动态文件。写操作不应该经常发生,可能最多每秒一次,并且通常比这慢得多。我想出了这个例子,似乎很管用 import copy import os.path import threading import tim

我有几个python进程,它们监视物理IO并对其进行操作。例如,如果电流过高,则关闭电机。他们需要让对方知道他们为什么要做某事,所以我认为共享文件可能是一个简单的解决方案。各种进程都可以写入该文件,其他进程需要知道该文件何时被写入。我已经将ConfigObj用于静态配置文件,所以我想尝试一下动态文件。写操作不应该经常发生,可能最多每秒一次,并且通常比这慢得多。我想出了这个例子,似乎很管用

import copy
import os.path
import threading
import time
from configobj import ConfigObj

class config_watcher(threading.Thread):
    def __init__(self,watched_items):
        self.watched_items = watched_items
        self.config = self.watched_items['config'] 
        super(config_watcher,self).__init__()
    def run(self):
        self.reload_config()
        while 1:
            # First look for external changes
            if self.watched_items['mtime'] <> os.path.getmtime(self.config.filename):
                print "external chage detected"
                self.reload_config()
            # Now look for external changes
            if self.watched_items['config'] <> self.watched_items['copy']: 
                print "internal chage detected"
                self.save_config()
            time.sleep(.1)
    def reload_config(self):
        try:
            self.config.reload()
        except Exception:
            pass
        self.watched_items['mtime'] = os.path.getmtime(self.config.filename)
        self.watched_items['copy'] = copy.deepcopy(self.config)
    def save_config(self):
        self.config.write()
        self.reload_config()

if __name__ == '__main__':
    from random import randint
    config_file = 'test.txt'
    openfile = open(config_file, 'w')
    openfile.write('x = 0 # comment\r\n')
    openfile.close()
    config = ConfigObj(config_file)
    watched_config = {'config':config} #Dictionary to pass to thread
    config_watcher = config_watcher(watched_config) #Start thread
    config_watcher.setDaemon(True) # and make it a daemon so we can exit on ctrl-c
    config_watcher.start()
    time.sleep(.1) # Let the daemon get going
    while 1:
        newval = randint(0,9)
        print "is:{0} was:{1}, altering dictionary".format(newval,config['x'])
        config['x'] = newval
        time.sleep(1)
        openfile = open(config.filename, 'w')
        openfile.write('x = {0} # external write\r\n'.format(randint(10,19)))
        openfile.close()
        time.sleep(1)
        print "is {1} was:{0}".format(newval,config['x'])
        time.sleep(1)
导入副本
导入操作系统路径
导入线程
导入时间
从configobj导入configobj
类配置监视程序(threading.Thread):
定义初始项(自我、监视项):
self.wasted_items=监视的_项
self.config=self.wasted_项目['config']
超级(配置观察者,自我)。\uuuu初始化
def运行(自):
self.reload_config()
而1:
#首先寻找外部变化
如果self.wasted_items['mtime']os.path.getmtime(self.config.filename):
打印“检测到外部变化”
self.reload_config()
#现在看看外部变化
如果self.wasted_项目['config']self.wasted_项目['copy']:
打印“检测到内部变化”
self.save_config()
时间。睡眠(.1)
def重新加载_配置(自身):
尝试:
self.config.reload()
除例外情况外:
通过
self.wasted_items['mtime']=os.path.getmtime(self.config.filename)
self.wasted_items['copy']=copy.deepcopy(self.config)
def保存配置(自我):
self.config.write()
self.reload_config()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
从随机导入randint
配置文件='test.txt'
openfile=open(配置文件“w”)
openfile.write('x=0#注释\r\n')
openfile.close()
config=ConfigObj(配置文件)
监视要传递给线程的_config={'config':config}#字典
config_watcher=config_watcher(watched_config)#启动线程
配置_watcher.setDaemon(True)#并使其成为一个守护进程,以便我们可以在ctrl-c上退出
config_watcher.start()
时间。睡眠(.1)#让守护进程开始运行
而1:
newval=randint(0,9)
打印“is:{0}was:{1},正在更改字典”。格式(newval,config['x'])
配置['x']=newval
时间。睡眠(1)
openfile=open(config.filename,“w”)
openfile.write('x={0}#外部写入\r\n'.格式(randint(10,19)))
openfile.close()
时间。睡眠(1)
打印“is{1}was:{0}”。格式(newval,config['x'])
时间。睡眠(1)

我的问题是,是否有更好/更容易/更干净的方法

如果有多个进程试图监视和更新相同的文件,则您的方法容易受到竞争条件的影响

为此,我倾向于使用SQLite,制作一个带有时间戳的“日志”表来记录消息。“monitor”线程可以只检查最大时间戳或整数键值。我知道,有人会说这太过分了,但我相信,一旦你在系统中拥有了一个共享数据库,你就会发现它还有其他一些巧妙的用途


作为奖励,您可以获得可审核性;更改的历史记录可以记录在表中

如果有多个进程试图监视和更新相同的文件,则您的方法容易受到竞争条件的影响

为此,我倾向于使用SQLite,制作一个带有时间戳的“日志”表来记录消息。“monitor”线程可以只检查最大时间戳或整数键值。我知道,有人会说这太过分了,但我相信,一旦你在系统中拥有了一个共享数据库,你就会发现它还有其他一些巧妙的用途


作为奖励,您可以获得可审核性;更改的历史记录可以记录在表中

> P>对于您描述的用例,即:多进程隔离和通信,您应该认真考虑<强> ReISIS < /强>作为SQL RDBMS的替代。

引用Redis实验室首席执行官Ofer Bengal的话

“Redis是一个键值数据库,[…]一个数据结构引擎”

总之,

  • 由于其通用的数据管理命令,它非常灵活
  • 它支持事务
  • 它重量轻,速度快
  • 如有必要,您可以将其配置为只读(磁盘上无写操作)
  • 它是稳定的,可用于多种计算平台
有关Redis交易的更多信息,您可以查看:


对于您描述的用例,即:多进程隔离和通信,您应该认真考虑<强> ReISIS < /强>作为SQL RDBMS的替代。

引用Redis实验室首席执行官Ofer Bengal的话

“Redis是一个键值数据库,[…]一个数据结构引擎”

总之,

  • 由于其通用的数据管理命令,它非常灵活
  • 它支持事务
  • 它重量轻,速度快
  • 如有必要,您可以将其配置为只读(磁盘上无写操作)
  • 它是稳定的,可用于多种计算平台
有关Redis交易的更多信息,您可以查看:


我确实知道如何获得比赛条件。我希望,因为这是基于物理IO的,所以这可能是可以避免的。我确实喜欢使用数据库的想法,但是在数据库中使用python超出了我的经验,我的数据库经验主要是使用dbase4。SQLite非常简单,它将其数据库存储在一个文件中,您可以使用命令行客户机查看该文件。在查找文档时,Python的接口称为“DB-API”。有一个“pysqlite”包为SQ实现它