python - pathlib / configparser 的气流问题 - “PosixPath”对象不可迭代
问题描述
我正在尝试将我的气流设置容器化。我的任务是保持环境不变,只需将其移动到 docker 容器中即可。我们目前在 anaconda 环境中安装了 Airflow 和所有依赖项。所以我所做的是创建了一个自定义 docker 镜像,它安装了 anaconda 并创建了我的环境。问题是,我们当前的环境使用 systemd 服务来启动气流,Docker 需要它通过气流命令“airflow webserver/scheduler/worker”运行它,当我这样运行它时,我得到一个错误。启动调度程序后出现错误。
我们的 DAG 需要一个自定义存储库来帮助与我们的数据库服务器进行通信。在该 repo 中,我们使用 pathlib 获取配置文件的路径并将其传递给 configparser。
基本上是这样的:
import configparser
from pathlib import Path
config = configparser.ConfigParser()
p = Path(__file__)
p = p.parent
config_file_name = 'comms.conf'
config.read(p.joinpath('config', config_file_name))
这会为我在 Airflow 中的所有 DAG 引发以下错误:
Broken DAG: [/opt/airflow/dags/example_folder/example_dag.py] 'PosixPath' object is not iterable
在命令行上,错误是:
[2021-01-11 19:53:13,868] {dagbag.py:259} ERROR - Failed to import: /opt/airflow/dags/example_folder/example_dag.py
Traceback (most recent call last):
File "/opt/anaconda3/envs/airflow/lib/python3.7/site-packages/airflow/models/dagbag.py", line 256, in process_file
m = imp.load_source(mod_name, filepath)
File "/opt/anaconda3/envs/airflow/lib/python3.7/imp.py", line 172, in load_source
module = _load(spec)
File "<frozen importlib._bootstrap>", line 696, in _load
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/opt/airflow/example_folder/example_dag.py", line 8, in <module>
dag = Dag()
File "/opt/airflow/dags/util/dag_base.py", line 27, in __init__
self.comms = get_comms(Variable.get('environment'))
File "/opt/airflow/repository/repo_folder/custom_script.py", line 56, in get_comms
config = get_config('comms.conf')
File "/opt/airflow/repository/repo_folder/custom_script.py", line 39, in get_config
config.read(p.joinpath('config', config_file_name))
File "/opt/anaconda3/envs/airflow/lib/python3.7/site-packages/backports/configparser/__init__.py", line 702, in read
for filename in filenames:
TypeError: 'PosixPath' object is not iterable
我能够在 docker 容器之外复制这种行为,所以我认为这与它没有任何关系。气流作为系统服务运行的方式与通过cli运行的方式之间必须有所不同吗?
这是我工作的气流服务文件:
[Unit]
Description=Airflow webserver daemon
After=network.target postgresql.service mysql.service redis.service rabbitmq-server.service
Wants=postgresql.service mysql.service redis.service rabbitmq-server.service
[Service]
EnvironmentFile=/etc/sysconfig/airflow
User=airflow
Group=airflow
Type=simple
ExecStart=/opt/anaconda3/envs/airflow/bin/airflow webserver
Restart=on-failure
RestartSec=5s
PrivateTmp=true
[Install]
WantedBy=multi-user.target
这是我在服务文件中使用的气流环境文件。请注意,我需要在本地导出这些环境变量以使气流在 cli 中运行到这一点。另请注意,自定义存储库位于 /opt/airflow 目录中。
AIRFLOW_CONFIG=/opt/airflow/airflow.cfg
AIRFLOW_HOME=/opt/airflow
PATH=/bin:/opt/anaconda3/envs/airflow/bin:/opt/airflow/etl:/opt/airflow:$PATH
PYTHONPATH=/opt/airflow/etl:/opt/airflow:$PYTHONPATH
我的气流配置是默认的,除了以下更改:
executor = CeleryExecutor
sql_alchemy_conn = postgresql+psycopg2://airflow:airflow@192.168.x.x:5432/airflow
load_examples = False
logging_level = WARN
broker_url = amqp://guest:guest@127.0.0.1:5672/
result_backend = db+postgresql://airflow:airflow@192.168.x.x:5432/airflow
catchup_by_default = False
配置解析器==3.5.3
我的 conda 环境使用的是 python 3.7,airflow 版本是 1.10.14。它在 Centos7 服务器上运行。如果有人有任何可以帮助的想法,我会适当的!
编辑:如果我将行更改为config.read(p.joinpath('config', config_file_name))
直接指向这样的配置,config.read('/opt/airflow/repository/repo_folder/config/comms.conf')
它可以正常工作。那么它与configparser如何处理pathlib输出有关吗?但是,如果气流通过 systemd 服务运行,这没有问题吗?
Edit2:我也可以将 pathlib 对象包装在 str() 中,它可以工作。config.read(str(p.joinpath('config', config_file_name)))
我只是想知道为什么这与 systemd 服务配合得很好。我担心其他东西会被破坏?
解决方案
配置文件的路径计算错误。
这是因为以下行
# filename: custom_script.py
p = p.parent
confpath = p.joinpath('config', config_file_name))
confpath
评估为/opt/airflow/repository/repo_folder/config/comms.conf
您共享的配置文件所在的路径是/opt/airflow/repository/repo_folder/conn.conf
.
您需要repo_folder
通过使用文件夹所在的路径构造其路径来解析配置文件custom_script.py
。
# filename: custom_script.py
from pathlib import Path
p = Path(dirname(__file__))
p = p.parent
confpath = p.joinpath(config_file_name)
推荐阅读
- laravel - Vuejs 是否需要 FormData 对象才能将文件上传到 laravel 后端?
- python - 为什么 UserDict 的 __copy__ 和 copy() 的行为不一致
- swift - 快速将多个图像从集合视图保存到 Firebase 存储并获取 downloadURL?
- node.js - TeamCity、NodeJS 和 API 测试
- pyqt5 - 按下按钮时创建按钮
- python - 从 Google 抓取/提取 Skype ID
- angular - 如何在 Angular 中使用 ngModel 预填充表单
- ios - 如何获取 NSPropertyDescription 属性的新旧值
- javascript - 有没有办法让类构造函数像普通函数一样被调用?
- excel - 范围变量(重新)赋值