关于python:如何将Airflow与Pywikibot一起使用

How to use Airflow with Pywikibot

当在 DAG 文件(或 DAG 文件导入的模块)中导入 pywikibot 时,DAG 会损坏,并在网络服务器 UI 中引发错误:

1
Broken DAG: [/path/to/airflow/dags/dag.py] encode() argument 1 must be str, not bool

我试图找到一个堆栈跟踪,但在 airflow/logs 中进行搜索却找不到任何东西。运行 airflow list_dags 成功运行并且无助于调试问题(如本问题所建议的那样),即使使用 --report.

因此,我的问题是:如何在 Airflow DAG 任务中使用 Pywikibot?

我在下面添加了其他信息,以展示我迄今为止所做的尝试。找到答案后,可以删除这个,让问题更简洁。

以下是示例 DAG 的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from airflow import DAG
from airflow.operators.python_operator import PythonOperator
from datetime import timedelta, datetime

#### this part is typically imported from another module ####
# to import, pywikibot requires `user-config.py` file or this env variable
import os
os.environ['PYWIKIBOT_NO_USER_CONFIG'] = '1'
import pywikibot
def do_nothing():
    pass
#############################################################

dag = DAG('try_pywikibot', schedule_interval=timedelta(days=1))

default_args = {
    'start_date': datetime(2019,1,1),
}

task1 = PythonOperator(
    python_callable=do_nothing,
    task_id=f'do_nothing',
    dag=dag,
    default_args=default_args,
)

关于导入 pywikibot 的注意事项:
Pywikibot 要求在工作目录中有一个配置文件 ,除非将 PYWIKIBOT_NO_USER_CONFIG 环境变量指定为 0。此类文件的示例:

1
2
3
family = 'wikipedia' # required
mylang = 'en' # required
# verbose_output = 0  # optional

我认为这可能是因为 pywikibot 的日志记录(发送 bool?)。可以通过在 pywikibot 的配置文件 (user-config.py) 中添加 verbose_output = 0 来关闭详细日志记录,但这并不能解决问题。

奇怪的是,运行这个简单的脚本

1
2
import pywikibot
import airflow

带有 verbose_output=0user-config.py 文件仍会从 pywikibot 输出详细日志。但是,当不导入 Airflow 时,它会在没有任何日志输出的情况下运行。但是,我尝试通过修改库的 logging.logoutput() 来完全禁用 pywikibot 的日志记录,即使导入了 Airflow,它也会禁用日志记录,但 DAG 仍然被 Airflow 视为损坏。

手动触发 DAG 时 DAG 确实"启动",但任务从不排队;他们仍然停留在状态 None.


console_encoding="utf-8" 行添加到 pywikibot 的配置 user-config.py 中就可以了。

为什么,我不通过 Airflow 运行时,Pywikibot 似乎无法加载 console_encodingutf-8 的默认值。因为 pywikibot 的 transliterator 是预先加载的,这会导致 ln 处的 pywikbot.userinterfaces.transliteration.py 失败。第1108章

奇怪的是,pywikibot 似乎期望一个布尔值,现在抛出

1
_DifferentTypeError: Configuration variable"console_encoding" is defined as"str" in your user-config.py but expected"bool".

但是,这可以放心地忽略。


我遇到了类似的问题,谷歌把我带到了这里。
此解决方案不会解决您的问题,看起来您以不同的方式解决了问题。但是,这可能对其他人有所帮助:

https://phabricator.wikimedia.org/T272088

解决方法是初始化记录器并更改pywiki的logLevel:

1
2
3
4
5
import logging
import pywikibot
pywikibot.output('This will initialize the logger')
logger = logging.getLogger('pywiki')
logger.setLevel(logging.WARNING)

这是一个解决方法,直到它被修复!

只是一个友好的下次,如果你能说明你使用哪个python/pywikibot版本,它也可以帮助其他人;)


要么:

  • 框架的 config2.py 已更改,这是永远不应该做的。

  • Pywikibot 可能已经过时了。 console_encoding默认是sys.stdout.encoding,应该是'utf-8'.

  • 这取决于你的 Python 和 Pywikibot 版本。