pathlib / configparser 的气流问题 - 'PosixPath' 对象不可迭代
Airflow issue with pathlib / configparser - 'PosixPath' object is not iterable
我正在尝试将我的气流设置容器化。我的任务是保持环境不变,只需将其移动到 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 容器之外复制此行为,所以我认为这与它没有任何关系。 airflow 运行s 作为 systemd 服务和它如何通过 cli 运行s 之间一定是有区别的?
这是我的 airflow 服务文件:
[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
这是我在服务文件中使用的气流环境文件。请注意,我需要在本地导出这些 env 变量,以使气流达到 运行,直至 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
configparser==3.5.3
我的conda环境使用的是python3.7,airflow版本是1.10.14。它在 Centos7 服务器上 运行ning。如果有人有任何可以帮助的想法,我会采纳!
编辑:如果我将行 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
。
您需要通过使用 custom_script.py
所在的文件夹构建其路径来解析相对于 repo_folder
的配置文件。
# filename: custom_script.py
from pathlib import Path
p = Path(dirname(__file__))
p = p.parent
confpath = p.joinpath(config_file_name)
我可以通过卸载并安装较新版本的 configparser 来解决这个问题。
configparser==5.0.1
我正在尝试将我的气流设置容器化。我的任务是保持环境不变,只需将其移动到 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 容器之外复制此行为,所以我认为这与它没有任何关系。 airflow 运行s 作为 systemd 服务和它如何通过 cli 运行s 之间一定是有区别的?
这是我的 airflow 服务文件:
[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
这是我在服务文件中使用的气流环境文件。请注意,我需要在本地导出这些 env 变量,以使气流达到 运行,直至 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
configparser==3.5.3
我的conda环境使用的是python3.7,airflow版本是1.10.14。它在 Centos7 服务器上 运行ning。如果有人有任何可以帮助的想法,我会采纳!
编辑:如果我将行 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
。
您需要通过使用 custom_script.py
所在的文件夹构建其路径来解析相对于 repo_folder
的配置文件。
# filename: custom_script.py
from pathlib import Path
p = Path(dirname(__file__))
p = p.parent
confpath = p.joinpath(config_file_name)
我可以通过卸载并安装较新版本的 configparser 来解决这个问题。
configparser==5.0.1