DagsterImportError:无法从datasets导入URL,求技术排查
导入自定义模块时与第三方库重名导致的导入错误问题
问题场景与错误信息
通过dagster project scaffold --name dagster_pipeline创建Dagster项目后,运行dagster dev时遇到导入错误:在自定义的datasets.py中定义了URL常量,在assets.py中使用from datasets import URL导入时,Python错误地加载了site-packages中的第三方datasets库,而非本地自定义模块,抛出cannot import name 'URL' from 'datasets'错误。
相关代码
assets.py:
import requests from dagster import asset from datasets import URL @asset def datasets(url: str = URL) -> str: return requests.get(url).text
init.py(未修改):
from dagster import Definitions, load_assets_from_modules from . import assets all_assets = load_assets_from_modules([assets]) defs = Definitions( assets=all_assets, )
错误信息
dagster._core.errors.DagsterImportError: Encountered ImportError: `cannot import name 'URL' from 'datasets' (C:\Users\agevorgyan\AppData\Local\Programs\Python\Python311\Lib\site-packages\datasets\__init__.py)` while importing module dagster_pipeline. Local modules were resolved using the working directory `C:\Users\agevorgyan\IdeaProjects\{project_name}\dagster_pipeline`. If another working directory should be used, please explicitly specify the appropriate path using the `-d` or `--working-directory` for CLI based targets or the `working_directory` configuration option for workspace targets.
问题原因
这不是Dagster的bug,是Python导入机制的正常行为:Python在查找模块时,会优先搜索site-packages目录下的第三方库,再搜索本地项目目录。当本地自定义模块与第三方库同名时,第三方库会被优先加载,导致找不到本地模块中的内容。
解决办法
方法1:使用相对导入
由于datasets.py和assets.py处于同一个项目包下,使用相对导入可以明确指定导入本地模块:
修改assets.py的导入语句:
import requests from dagster import asset # 用相对导入指向当前包下的datasets模块 from .datasets import URL @asset def datasets(url: str = URL) -> str: return requests.get(url).text
方法2:重命名自定义模块
直接修改本地模块文件名,避免与第三方库重名,比如将datasets.py改为project_datasets.py,再修改assets.py的导入语句:
import requests from dagster import asset from project_datasets import URL @asset def datasets(url: str = URL) -> str: return requests.get(url).text
方法3:调整sys.path优先级(不推荐)
手动将项目目录添加到sys.path的最前面,强制Python优先加载本地模块,但这种方法容易引发其他导入冲突,不建议使用:
import sys from pathlib import Path # 将当前文件所在目录插入到sys.path首位 sys.path.insert(0, str(Path(__file__).parent)) import requests from dagster import asset from datasets import URL @asset def datasets(url: str = URL) -> str: return requests.get(url).text
内容的提问来源于stack exchange,提问作者Albert Gevorgyan
相关产品推荐
相关产品推荐

