在容器中托管简单的python脚本来处理并发,配置,缓存等

时间:2010-06-01 22:21:45

标签: plugins dependency-injection ioc-container python

我的第一个真实世界的Python项目是编写一个简单的框架(或重新使用/改编现有的框架),它可以用“容器”包装小的python脚本(用于收集监视工具的自定义数据) “处理如下的样板任务:

  • 从文件中获取脚本的配置(如果文件更改并处理敏感配置数据的解密,则保持该信息的最新状态)
  • 在不同的线程中运行相同脚本的多个实例,而不是为每个线程启动一个新进程
  • 公开一个API,用于缓存昂贵的数据并将持久状态从一个脚本调用存储到下一个

今天,脚本作者必须处理上述问题,这通常意味着大多数脚本作者都没有正确处理它们,从而导致错误和性能问题。除了避免错误之外,我们还需要一个能够降低创建和维护脚本的解决方案,特别是考虑到许多脚本作者可能不是经过培训的程序员。

以下是我一直在考虑的API示例,我希望得到您的反馈意见。

脚本编写者需要构建一个单独的方法,该方法接受(作为输入)脚本完成其工作所需的配置,并返回python对象或调用方法以块的形式流回数据。可选地,脚本编写者可以提供处理启动和/或关闭任务的方法。

HTTP抓取脚本示例(在伪代码中,省略实际的数据获取细节以专注于容器的API):

def run (config, context, cache) : 
    results = http_library_call (config.url, config.http_method, config.username, config.password, ...) 
    return { html : results.html, status_code : results.status, headers : results.response_headers }

def init(config, context, cache) : 
     config.max_threads = 20  # up to 20 URLs at one time (per process) 
     config.max_processes = 3  # launch up to 3 concurrent processes 
     config.keepalive = 1200  # keep process alive for 10 mins without another call
     config.process_recycle.requests = 1000  # restart the process every 1000 requests (to avoid leaks) 
     config.kill_timeout = 600  # kill the process if any call lasts longer than 10 minutes 

数据库数据获取脚本示例可能如下所示(在伪代码中):

def run (config, context, cache) : 
    expensive = context.cache["something_expensive"] 
    for record in db_library_call (expensive, context.checkpoint, config.connection_string) : 
        context.log (record, "logDate")  # log all properties, optionally specify name of timestamp property 
        last_date = record["logDate"] 
    context.checkpoint = last_date  # persistent checkpoint, used next time through 

def init(config, context, cache) : 
    cache["something_expensive"] = get_expensive_thing() 

def shutdown(config, context, cache) : 
    expensive = cache["something_expensive"] 
    expensive.release_me()

这个API是否适当地“pythonic”,或者我应该做些什么来使Python脚本更自然? (我对构建C ++ / C#/ Java API比较熟悉,所以我怀疑我缺少有用的Python习语。)

具体问题:

  • 将“config”对象传递给方法并让被调用者设置各种配置选项是很自然的吗?或者还有另一种首选方式吗?
  • 当被调用者需要将数据流回其调用者时,类似context.log()(见上文)的方法是否恰当,或者我应该使用yield吗? (yeild看起来很自然,但我担心它会超过大多数脚本编写者的头脑)
  • 我的方法需要脚本来定义具有预定义名称的函数(例如“run”,“init”,“shutdown”)。这是一个很好的方法吗?如果没有,那么其他什么机制会更自然?
  • 我将相同的config, context, cache参数传递给每个方法。改为使用单个“上下文”参数会更好吗?改为使用全局变量会更好吗?
  • 最后,您是否建议使用现有的库来使这种简单的“脚本运行容器”更易于编写?

1 个答案:

答案 0 :(得分:0)

看看SQL Alchemy处理python中的数据库内容。另外,为了使脚本编写更容易处理并发性,请查看Stackless Python。