在Jupyter笔记本中如何将Python文件作为模块导入?

6
我正在开发 AWS Glue 脚本,并尝试使用 Dev Endpoint。我按照向导创建了 Dev Endpoint 和附加到它的 SageMaker 笔记本。当我打开 SageMaker 笔记本时,它会将我重定向到一个名为 Jupyter 的网页。
在 Jupyter 中,我创建了几个带有我的 Python 文件的笔记本。问题是,一些共享的 Python 文件不能作为模块导入到笔记本中。我得到了以下错误: “未找到 shared.helper 模块 Traceback (most recent call last):”
这是我在 Jupyter 笔记本上的项目结构:
my_project/
│
├── scripts/
│   ├── a_notebook.ipynb
│   ├── b_notebook.ipynb
|   ├── c_notebook.ipynb
│   ├── __init__.py     
│   └── shared/
         └── helper.py
         └── config.py
         └── __init__.py

我尝试了许多在互联网上搜索到的方法,但都没有奏效。

a_notebook.ipynb 中,我只使用了 import shared.helper as helper,但是出现了上述错误。

我不知道这是否与 AWS Glue 有关?因为我是从 AWS Glue 控制台下的 Sagemaker 笔记本打开 Jupyter。


即使我尝试将Python文件放在与笔记本文件相同的文件夹中,它仍然无法工作并显示相同的错误。 - Bill Li
2个回答

6

TLDR

根据文档,您需要将Python文件上传到S3存储桶中。如果有多个文件,则需要将它们压缩成zip文件。当您启动开发端点时,在安全配置、脚本库和作业参数(可选)下有一个设置Python库路径,用于设置包含自定义库(包括脚本、模块、包)的S3存储桶的路径。您还需要确保分配给开发端点使用的IAM角色的IAM策略具有对该存储桶进行列表/头部/获取对象等操作的访问权限。

详细信息

这需要一些额外的工作,但主要原因是需要将库加载到Spark集群中的每个DPU(执行容器)中。

当您使用Sparkmagic(pyspark)内核时,它会使用一个名为livy的Spark库来连接并在远程Spark集群上运行您的代码。dev endpoint实际上是一个Spark集群,而您的"Sagemaker笔记本"正在连接到Spark集群上的livy主机。
这与普通的Python环境非常不同,主要是因为当前工作目录和代码执行的位置不是同一个地方。 Sagemaker允许使用许多Jupyter magics,因此您可以测试一下并查看结果。
例如,在段落中运行以下内容:
%pwd

它将显示您期望看到的内容,类似于

/home/ec2-user/SageMaker

并尝试这个:

%ls

我会尽力为您进行翻译,以下是需要翻译的内容:

然后你会看到类似这样的东西

Glue Examples/ lost+found/ shared/ a_notebook.ipynb

这些魔法使用笔记本的上下文,并向您显示与其相关的目录。 如果您尝试这样做:

import os
print(os.getcwd())

你会看到完全不同的东西:

/mnt/yarn/usercache/livy/appcache/application_1564744666624_0002/

这是来自集群上驱动程序容器的Spark(实际上是hadoop HDFS)目录。 Hadoop目录具有冗余分布,因此不能正确地说该目录位于该容器中,也不是非常重要。 关键是该目录位于远程集群上,而不是运行笔记本电脑的EC2实例上。
有时,加载模块的一个好技巧是修改您的sys.path以包括要从中导入模块的目录。 不幸的是,这在这里不起作用,因为如果将/home/ec2-user/Sagemaker附加到路径中,则首先该路径在HDFS上不存在,其次pyspark上下文无法搜索您的笔记本电脑的EC2主机上的路径。
您可以做的另一件事是更改正在运行的笔记本电脑中的内核。 Jupyter中有一个kernel菜单选项。 我建议使用conda_python3
当然,这个内核不会连接到Spark集群,因此任何Spark代码都无法运行,但您可以尝试上面的% pwdprint(os.getcwd())测试,查看它们是否显示相同的本地目录。您还应该能够导入模块,尽管可能需要修改路径,例如:
import os
import sys
shared_path = '/home/ec2-user/SageMaker/shared'
if shared_path not in sys.path:
    sys.path.append(shared_path)

然后您应该能够运行此代码

import helper

但是此时,您不在Sparkmagic(pyspark)内核中,所以这对您没有好处。

这是一个长的解释,但它应该有助于清楚地说明为什么需要将脚本上传到S3存储桶。当您的开发终端点启动时,它具有从该位置加载自定义库的钩子,因此它们可用于Spark集群容器。

^ 请注意,Sagemaker是Jupyter笔记本电脑的AWS重新品牌,这有点令人困惑。 Sagemaker也是AWS中用于自动化机器学习模型训练/测试/部署生命周期管理的服务的名称。它本质上是Jupyter笔记本加上一些调度加上一些API端点。我会很惊讶如果它不是在幕后运行像papermill这样的东西。


5

您可以使用以下方法将模块导入 Spark:

spark.sparkContext.addPyFile("<hdfs_path>/foo.py")

那么就像这样导入它:

import foo
from foo import bar
Azure: "abfs://<container>@<storage_account>.dfs.core.windows.net/foo/bar.py"
AWS: "s3://<bucket>/foo/bar.py"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接