繁体   English   中英

带有Docker的Python Luigi-线程/信号问题

[英]Python Luigi with Docker - Threading/Signal issue

概观

我们正在使用Luigi在Docker容器内构建管道。 这是我第一次使用Luigi,并且试图使它运行,但是我遇到了Python线程/信号错误。

我们正在建造
我们有一个运行setup.py脚本作为入口点的容器。 该脚本导入了我的Luigi任务,但其主要功能是为Google Cloud Services打开PubSub通道。 当它在该频道上收到消息时,它将启动一系列任务。

错误
我直接从Python调用Luigi,尝试使用以下命令:

luigi.build([GetImageSet()], workers=2, local_scheduler=True, no_lock=True)

并收到此错误:

ValueError: signal only works in main thread


Signal和Luigi的背景

从Python Signal模块文档中:
signal.signal: 只能从主线程调用此函数; 尝试从其他线程调用它会导致引发ValueError异常。

此处的Luigi worker.py脚本
Luigi提供了no_install_shutdown_handler标志(默认为false)。 “如果为true,则不会在worker上安装SIGUSR1关闭处理程序”。 这也是发生错误的地方(第538行)。 该脚本在运行signal.signal()之前检查no_install_shutdown_handler的配置标志是否为(默认)false。 到目前为止,我未能使Luigi读取该标志设置为true的client.cfg文件,而可能是Docker造成的。

从Luigi interface.py脚本在这里
如果您不想从命令行运行luigi。 您可以使用此模块中定义的方法以编程方式运行luigi。 在此脚本中,我可以提供一个自定义的工作人员计划工厂,但是我还无法解决这个问题。

本地与全局Luigi调度程序
Luigi提供了两个调度程序选项来运行任务。 本地的

Dockerfile麻烦 :在此容器的Dockerfile中,我通过pip安装Luigi,但没有做其他事情。 在回顾了github上的这个这个 docker / luigi实现之后,我开始担心我在Dockerfile中做得不够。


我认为发生错误的可能原因

  1. pub-sub通道订阅者是非阻塞的,因此我正在做一些可能很糟糕的事情,以防止我们在后台等待消息时退出主线程。 这似乎是我的线程问题的根源。
  2. no_install_shutdown_handler标志未成功设置为True,这有望绕过错误,但不一定是我想要的
  3. 本地任务计划程序。 我应该使用全局调度程序而不是本地调度程序。 无论如何,我最终将不得不将其投入生产。
  4. 从Python而不是命令行运行脚本
  5. 使用luigi.build 相反,我应该使用luigi.run ,但是根据“从Python运行 ”的文档页面luigi.run ,“如果要从其他来源(例如数据库)获取一些动态参数,或者在启动任务之前提供其他逻辑,则很有用。” 听起来这很适合我的用例(从发布订阅频道接收到传递运行第一个任务所需的变量的消息后触发任务)

反正我做错了吗? 如果您对实施上述系统有任何建议,请告诉我。 我还将根据请求发布Dockerfile和setup.py尝试。


一些代码示例

这是Dockerfile

# ./Dockerfile
# sfm-base:test is the container with tensorflow & our python sfm-library. It installs Ubuntu, Python, pip etc.
FROM sfm-base:test
LABEL maintainer "---@---.io"

# Install luigi, google-cloud w/ pip in module mode
RUN python -m pip install luigi && \
python -m pip install --upgrade google-cloud

# for now at least, start.sh just calls setup.py and sets google credentials. Ignore that chmod bit if it's bad I don't know.
COPY start.sh /usr/local/bin
RUN chmod -R 755 "/usr/local/bin/start.sh"
ENTRYPOINT [ "start.sh" ]

WORKDIR /src
COPY . .

# this was my attempt at setting the Luigi client.cfg in the container
# all I'm having the config do for now is set [core] no_install_shutdown_handler: true
ENV LUIGI_CONFIG_PATH /src/client.cfg

这是setup.py(为SO进行了编辑)

# setup.py
from google.cloud import pubsub_v1
from time import sleep
import luigitasks
import luigi
import logging
import json

subscriber = pubsub_v1.SubscriberClient()
subscription_path = subscriber.subscription_path(
'servicename', 'pubsubcommand')

# Example task. These are actually in luigitasks.py
class GetImageSet(luigi.Task):
     uri = luigi.Parameter(default='')

     def requires(self):
          return []

     def output(self):
          # write zip to local
          return

     def run(self):
          # use the URI to retrieve the ImageSet.zip from the bucket
          logging.info('Running getImageSet')

# Pubsub message came in
def onMessageReceived(message):
     print('Received message: {}'.format(message))

     if message.attributes:
          for key in message.attributes:
               if key == 'ImageSetUri':
                    value = message.attributes.get(key)
                    # Kick off the pipeline starting with the GetImageSet Task
                    # I've tried setting no_lock, take_lock, local_scheduler...
                    # General flags to try and prevent the thread issues
                    luigi.build([GetImageSet()], workers=3, local_scheduler=True, no_lock=False)
                    message.ack()

subscriber.subscribe(subscription_path, callback=onMessageReceived)

# The subscriber is non-blocking, so I keep the main thread from
# exiting to allow it to process messages in the background. Is this
# the cause of my woes?
print('Listening for messages on {}'.format(subscription_path))
while True:
    sleep(60)

发生这种情况是因为subscriber.subscribe启动了后台线程。 当该线程调用luigi.build ,将引发异常。

这里最好的解决方案是使用subscriber.pull从主线程读取pub-sub消息。 请参阅docs中的示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM