小能豆

运行 Python FLEX 模板时出错:无法找到子目录中的模块

py

我正在尝试使用 Flex 模板运行 Dataflow 作业,但我遇到了“未找到模块错误”,我无法弄清楚原因,所以这里是我的目录结构

|__ modules
  |____ edgar_quarterly_form4.py
  |____ __init__.py
|__ main.py
|__ setup.py
|__ __init__.py

我的 main.py 代码中有这个导入

from modules import edgar_quarterly_form4

这是我的dockerfile

FROM gcr.io/dataflow-templates-base/python3-template-launcher-base

ARG WORKDIR=/dataflow/template
RUN mkdir -p ${WORKDIR}
RUN mkdir -p ${WORKDIR}/modules
WORKDIR ${WORKDIR}

COPY spec/python_command_spec.json ${WORKDIR}/python_command_spec.json
COPY modules ${WORKDIR}/modules

ENV DATAFLOW_PYTHON_COMMAND_SPEC ${WORKDIR}/python_command_spec.json

RUN pip install avro-python3 pyarrow==0.15.1 apache-beam[gcp]==2.27.0

COPY __init__.py ${WORKDIR}/__init__.py
COPY setup.py ${WORKDIR}/setup.py 
COPY main.py ${WORKDIR}/main.py
# Super important to add these lines.
ENV FLEX_TEMPLATE_PYTHON_SETUP_FILE="${WORKDIR}/setup.py"
ENV FLEX_TEMPLATE_PYTHON_PY_FILE="${WORKDIR}/main.py"

这是我的 setup.py 文件

import setuptools

REQUIRED_PACKAGES = [
'numpy',
'beautifulsoup4',
'pandas',
'sendgrid==6.2.1',
'lxml',
'pandas_datareader',
'apache-beam[gcp]==2.27.0',
]
setuptools.setup(
   packages=setuptools.find_packages(),
install_requires=REQUIRED_PACKAGES,
)

但是,每次运行我的模板时都会出现此错误

368, in load_session module = unpickler.load() File "/usr/local/lib/python3.7/site- 
packages/dill/_dill.py", line 472, in load obj = StockUnpickler.load(self) File 
"/usr/local/lib/python3.7/site-packages/dill/_dill.py", line 827, in _import_module return 
 getattr(__import__(module, None, None, [obj]), obj) ModuleNotFoundError: No module named 
 'modules'

我不知道为什么。我向我的 docker 文件添加了一些 echo 来查看是否已复制所有文件,并且所有文件都已成功复制到映像中…所以我真的不知道发生了什么。请注意,即使 edgar_quarterly_form4.py 文件与 main.py 位于同一目录中,我也会收到完全相同的错误


阅读 19

收藏
2025-01-01

共1个答案

小能豆

从你的描述和提供的代码来看,ModuleNotFoundError: No module named 'modules' 的原因可能与 Python 的包结构、PYTHONPATH 环境变量设置、或 setup.py 的配置不正确有关。以下是可能的原因及解决方法:


问题 1: 模块未被 setup.py 识别

你的 setup.py 文件可能没有正确地将 modules 目录识别为一个包。

解决方法:

  1. 确保 modules 目录包含 __init__.py 文件(从你的目录结构来看,它是存在的)。
  2. 修改 setup.py,确保包能够被识别:
setuptools.setup(
    name='my_dataflow_package',
    version='0.1',
    packages=setuptools.find_packages(include=["modules", "modules.*"]),
    install_requires=REQUIRED_PACKAGES,
)

问题 2: 未正确设置 PYTHONPATH

运行 Dataflow 作业时,Python 可能无法正确识别 modules 包的路径。

解决方法:

  1. 在 Dockerfile 中设置 PYTHONPATH
    dockerfile ENV PYTHONPATH="${WORKDIR}:${WORKDIR}/modules"
    这确保了 Python 在运行时能够找到 modules 目录。

  2. 验证容器内部是否正确设置了路径:
    在构建的镜像中执行:
    sh python -c "import sys; print(sys.path)"
    检查是否包含 ${WORKDIR}${WORKDIR}/modules


问题 3: 模块未正确安装到 Dataflow 容器中

Flex Template 使用的 Dataflow 容器可能没有正确安装你的 Python 包。

解决方法:

  1. 确保在 Dockerfile 中添加了以下命令以安装你的包:
    dockerfile RUN pip install .
    这会根据你的 setup.py 安装所有依赖项及自定义模块。

  2. 确认镜像中安装了你的模块:
    在构建的镜像中运行以下命令:
    sh python -m pip list
    检查是否包含 modules 包。


问题 4: 数据流作业的序列化问题

Dataflow 的 apache_beam 使用序列化来传递代码和数据。如果你使用的模块未正确序列化,可能会导致 ModuleNotFoundError

解决方法:

  1. 使用 apache_beam.transforms.utilAsSourceAsSink 传递模块路径。
  2. 确保所有代码都包含在 main.py 中,而不是依赖动态加载的模块。

验证

完成修改后,请重新构建镜像并测试:
1. 清理旧镜像:
bash docker rmi <image_name>
2. 重新构建:
bash docker build -t <image_name> .
3. 验证模块是否正常运行:
bash docker run -it <image_name> python main.py

如果仍然出现错误,请提供你执行的具体命令和任何额外的日志,我可以进一步帮助你。

2025-01-01