在 pyspark 1.6.2 中,我可以通过以下方式导入 col
函数
from pyspark.sql.functions import col
但是当我尝试在 Github source code 中查找时,我在 functions.py
文件中找不到 col
函数,python 如何导入不存在的函数?
它存在。它只是没有明确定义。从 pyspark.sql.functions
导出的函数是 JVM 代码的精简包装器,除了需要特殊处理的少数例外情况外,它们是使用辅助方法自动生成的。
如果您仔细检查源you'll find col
listed among other _functions
。这个字典是 further iterated 并且 _create_function
用于生成包装器。每个生成的函数都直接分配给 globals
中的相应名称。
最后,定义从模块导出的项目列表的 __all__
仅导出所有 globals
,不包括黑名单中包含的项目。
如果此机制仍不清楚,您可以创建一个玩具示例:
创建名为 foo.py 的 Python 模块,其内容如下: # 创建一个分配给名称的函数 foo globals()["foo"] = lambda x: "foo {0}".format(x) # 从全局变量中导出所有条目以 foo __all__ = [x for x in globals() if x.startswith("foo")] 开头
将它放在 Python 路径上的某个位置(例如在工作目录中)。
导入 foo:从 foo 导入 foo foo(1)
这种元编程方法的一个不良副作用是,纯粹依赖于静态代码分析的工具可能无法识别定义的函数。这不是一个关键问题,可以在开发过程中安全地忽略。
根据 IDE,安装 type annotations 可能会解决问题(参见示例 zero323/pyspark-stubs#172)。
在 Pycharm 中,col
函数和其他函数被标记为“未找到”
https://i.stack.imgur.com/3dlSQ.png
一种解决方法是导入 functions
并从那里调用 col
函数。
例如:
from pyspark.sql import functions as F
df.select(F.col("my_column"))
从 VS Code 1.26.1 开始,这可以通过修改 python.linting.pylintArgs
设置来解决:
"python.linting.pylintArgs": [
"--generated-members=pyspark.*",
"--extension-pkg-whitelist=pyspark",
"--ignored-modules=pyspark.sql.functions"
]
该问题已在 github 上进行了解释:https://github.com/DonJayamanne/pythonVSCode/issues/1418#issuecomment-411506443
ignored-modules = pyspark.sql.functions
添加到我的 setup.cfg
如上所述,pyspark 会动态生成一些函数,这使得大多数 IDE 无法正确检测到它们。但是,有一个 python 包 pyspark-stubs 包含一组存根文件,以便改进类型提示、静态错误检测、代码完成……只需安装
pip install pyspark-stubs==x.x.x
(其中 xxx 必须替换为您的 pyspark 版本(例如,在我的情况下为 2.3.0)),col
和其他功能将被检测到,而无需更改大多数 IDE 代码中的任何内容(Pycharm、Visual Studio Code、原子,Jupyter 笔记本,...)
直接导入所有pyspark函数;
from pyspark.sql.functions import *
...
col('my_column')
您可能还想使用别名来解决函数阴影;
from pyspark.sql import functions as f
...
f.col('my_column')
import *
,因为它可能导致未知的导入或覆盖。
我在尝试使用 Eclipse 和 PyDev 设置 PySpark 开发环境时遇到了类似的问题。 PySpark 使用动态命名空间。为了让它工作,我需要将 PySpark 添加到“强制内置”,如下所示。
https://i.stack.imgur.com/EyjzM.png
正如@zero323 所指出的,有几个spark 函数在运行时通过添加到全局字典生成包装器,然后将它们添加到__all__
。正如@vincent-claes 所指出的,使用 function
路径(作为 F
或其他内容,我更喜欢更具描述性的内容)引用函数可以使导入不会在 PyCharm 中显示错误。但是,正如@nexaspx 在对该答案的评论中所暗示的那样,这会将警告转移到使用行。正如@thomas 提到的,可以安装 pyspark-stubs 来改善这种情况。
但是,如果由于某种原因添加该软件包不是一个选项(也许您正在为您的环境使用 docker 映像并且现在无法将其添加到映像中),或者它不起作用,这是我的解决方法:首先,为生成的带有别名的包装器添加一个导入,然后禁用仅对该导入的检查。这允许所有用法仍然在同一语句中检查其他功能,将警告点减少到只有一个,然后忽略那个警告。
from pyspark.sql import functions as pyspark_functions
# noinspection PyUnresolvedReferences
from pyspark.sql.functions import col as pyspark_col
# ...
pyspark_functions.round(...)
pyspark_col(...)
如果您有多个导入,请将它们分组为只有一个 noinspection
:
# noinspection PyUnresolvedReferences
from pyspark.sql.functions import (
col as pyspark_col, count as pyspark_count, expr as pyspark_expr,
floor as pyspark_floor, log1p as pyspark_log1p, upper as pyspark_upper,
)
(这就是我使用 Reformat File
命令时 PyCharm 对其进行格式化的方式)。
虽然我们正在讨论如何导入 pyspark.sql.functions
,但我建议不要从 pyspark.sql.functions
导入单个函数,以避免遮蔽 Python 内置函数,这可能会导致难以理解的错误,如 @SARose states。
不定期副业成功案例分享
Cannot find reference 'col' in 'functions.py'
警告......