我有几个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 # commentrn')
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 writern'.format(randint(10,19)))
openfile.close()
time.sleep(1)
print "is {1} was:{0}".format(newval,config['x'])
time.sleep(1)
我的问题是,是否有更好/更容易/更清洁的方法?
如果有多个进程试图监视和更新相同的文件,那么您的方法很容易受到竞争条件的影响。
我倾向于使用SQLite,制作一个带有时间戳的"日志"表来记录消息。"monitor"线程可以只检查最大时间戳或整数键值。我知道,有些人会说这太过分了,但我相信,一旦你在系统中有了共享数据库,你就会发现它的其他一些聪明用途
作为奖励,你可以获得可试镜性;可以将更改的历史记录在表中。
对于您描述的用例,即:多进程隔离和通信,您应该认真考虑Redis作为SQL RDBMS的替代方案。
引用 Redis实验室首席执行官Ofer Bengal的话
"Redis是一个键值数据库和[…]数据结构化引擎"
简而言之,
- 它非常灵活,这要归功于它的通用方法数据管理命令
- 它支持交易
- 它重量轻,速度快
- 如果需要,您可以将其配置为只读(不在磁盘上写入)
- 它是稳定的,可用于多个计算平台
有关Redis事务的更多信息,您可以查看:
- https://redislabs.com/ebook/redis-in-action/part-2-core-concepts-2/chapter-3-commands-in-redis/3-7-other-commands/3-7-2-basic-redis-transactions