如何在 Jupyter Notebook 中将 python 文件作为模块导入?

Bil*_* Li 3 python module amazon-web-services jupyter aws-glue

我正在开发 AWS Glue 脚本,并且正在尝试使用 Dev Endpoint。我按照向导创建了一个 Dev Endpoint 和一个附加到它的 SageMaker 笔记本。当我打开 SageMaker 笔记本时,它会将我定向到一个名为 Jupyter 的网页。

在 Jupyter 中,我用我的 python 文件创建了几个笔记本。问题是一些共享的 python 文件不能作为模块导入到笔记本中。我收到以下错误:“没有名为 shared.helper Traceback 的模块(最近一次调用):

导入错误:没有名为 shared.helper 的模块

这是我在 Jupyter 笔记本上的项目结构:

my_project/
?
??? scripts/
?   ??? a_notebook.ipynb
?   ??? b_notebook.ipynb
|   ??? c_notebook.ipynb
?   ??? __init__.py     
?   ??? shared/
         ??? helper.py
         ??? config.py
         ??? __init__.py
Run Code Online (Sandbox Code Playgroud)

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

在 中a_notebook.ipynb,我只是使用import shared.helper as helper,它向我显示了上述错误。

我不知道是否与 AWS Glue 有任何关系?当我从 AWS Glue 控制台下的 Sagemaker 笔记本打开 Jupyter 时。

Dav*_*vos 6

TLDR

根据文档

您需要将 Python 文件上传到 S3 存储桶。如果您有多个,则需要将它们压缩。当您启动dev的终点,有一个设置Python library pathSecurity configuration, script libraries, and job parameters (optional)的路径设置为包含S3存储自定义库(包括脚本,模块,包)。您还需要确保附加到开发终端节点使用的 IAM 角色的 IAM 策略可以访问该存储桶的 list/head/getobject 等。

细节

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

当您使用Sparkmagic (pyspark)内核时,它正在使用一个称为livy连接到远程 Spark 集群并在其上运行您的代码的 Spark 库。该dev endpoint实际上是一个Spark集群,而你的“Sagemaker笔记本” ^被连接到星火群集上的李维主机。

这与普通的 Python 环境有很大不同,主要是因为当前工作目录和代码执行的位置不同。Sagemaker 允许使用很多Jupyter 魔法,因此您可以测试一下并查看。

例如在一个段落中运行这个

%pwd
Run Code Online (Sandbox Code Playgroud)

它会向您展示您希望看到的内容,例如

/home/ec2-user/SageMaker

试试这个:

%ls
Run Code Online (Sandbox Code Playgroud)

你会看到这样的

胶水示例/lost+found/shared/a_notebook.ipynb

这些魔法使用 Notebook 的上下文并显示与它相关的目录。如果你试试这个:

import os
print(os.getcwd())
Run Code Online (Sandbox Code Playgroud)

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

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

这是HDFS来自集群上驱动程序容器的 Spark(实际上是 hadoop )目录。Hadoop 目录以冗余方式分布,因此说目录在该容器中不一定正确,这也不是很重要。关键是该目录在远程集群上,而不是在运行笔记本的 ec2 实例上。

有时加载模块的一个很好的技巧是修改您sys.path的目录以包含要从中导入模块的目录。不幸的是,这在这里不起作用,因为如果您附加/home/ec2-user/Sagemaker到路径,首先该路径在 HDFS 上将不存在,其次 pyspark 上下文无法搜索笔记本的 EC2 主机上的路径。

你可以做的另一件事来证明这一切都是真的,那就是在正在运行的笔记本中更改内核。kernelJupyter 中有一个菜单选项。我建议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)
Run Code Online (Sandbox Code Playgroud)

然后你应该能够运行这个

import helper
Run Code Online (Sandbox Code Playgroud)

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

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

^ 请注意,Sagemaker 是 Jupyter notebooks 的 AWS 品牌重塑,这有点令人困惑。Sagemaker 也是 AWS 中用于自动化机器学习模型训练/测试/部署生命周期管理的服务的名称。它本质上是 Jupyter 笔记本加上一些调度和一些 API 端点。如果不是像造纸厂那样在引擎盖下运行,我会感到惊讶。


小智 6

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

spark.sparkContext.addPyFile("<hdfs_path>/foo.py")
Run Code Online (Sandbox Code Playgroud)

然后只需将其导入即可:

import foo
from foo import bar
Run Code Online (Sandbox Code Playgroud)

HDFS 路径示例:

Azure: "abfs://<container>@<storage_account>.dfs.core.windows.net/foo/bar.py"
AWS: "s3://<bucket>/foo/bar.py"
Run Code Online (Sandbox Code Playgroud)