如何在虚拟环境中运行Airflow PythonOperator

时间:2018-04-09 17:09:54

标签: python virtualenv airflow

我有几个python文件,我目前正在使用BashOperator执行。这使我可以灵活地轻松选择python虚拟环境。

from airflow import DAG
from airflow.operators.bash_operator import BashOperator

default_args = {
   'owner': 'airflow',
    'depends_on_past': False,
    ...}

dag = DAG('python_tasks', default_args=default_args, schedule_interval="23 4 * * *")

t1 = BashOperator(
                 task_id='task1',
                bash_command='~/anaconda3/envs/myenv/bin/python 
                              /python_files/python_task1.py',
                 dag=dag)

如何使用PythonOperator实现相同的目标呢?

from airflow.operators.bash_operator import PythonOperator
import python_files.python_task1

python_task = PythonOperator(
              task_id='python_task',
              python_callable=python_task1.main,
             dag=dag)

我假设PythonOperator将使用系统python环境。 我发现Airflow有PythonVirtualenvOperator,但这似乎可以通过使用指定的要求动态创建新的虚拟环境来实现。我更喜欢使用已经正确配置的现有的。 如何使用指定的python路径运行PythonOperator?

2 个答案:

答案 0 :(得分:2)

首先要做的事情:您(通常)不应该依赖于运营商的预先存在的资源。您的操作员应该是便携式的,因此使用长期存在的技术有点违反该原则。话虽这么说,但这并不是什么大问题,就像你必须将软件包预先安装到全球环境中一样,你可以预先烘焙一些环境。或者,您可以让运营商创建环境,后续运营商可以重复使用它 - 我相信这是最简单,最危险的方法。

实现“virtualenv缓存”应该不难。阅读PythonVirtualenvOperator执行方法的实现:

PythonVirtualenvOperator

所以看起来它没有明确地删除virtualenv(它依赖于TemporaryDirectory来做到这一点)。您可以继承import glob @contextmanager def ReusableTemporaryDirectory(prefix): try: existing = glob.glob('/tmp/' + prefix + '*') if len(existing): name = existing[0] else: name = mkdtemp(prefix=prefix) yield name finally: # simply don't delete the tmp dir pass def execute_callable(self): with ReusableTemporaryDirectory(prefix='cached-venv') as tmp_dir: ... 并简单地使用您自己的上下文管理器来重用临时目录:

try-finally

当然,您可以摆脱ReusableTemporaryDirectory中的suffix并放回通常的dirTemporaryDirectory参数,我进行了微小的更改以便于比较使用原始的var hashKey = hash('foo') hashArray[hashKey] 类。

有了这个,你的virtualenv将不会被丢弃,但运营商最终会安装更新的依赖项。

答案 1 :(得分:1)

我的解决方法是使用Bash运算符调用/path/to/project/venv/bin/python my.py