如何在Python模块中封装支持R代码?
我正在尝试把一些Python代码打包,这些代码会调用R语言的代码,使用的是rpy2。目前,这段R代码保存在一个单独的文件里,我在Python脚本中通过source
来调用它。例如,如果我的Python脚本是myscript.py
,那么R代码就存储在myscript_support.R
文件里,在myscript.py
中我有类似下面的内容:
from rpy2.robjects import *
# Load the R code
r.source(os.path.join(os.path.dirname(__file__), "myscript_support.R"))
# Call the R function
r[["myscript_R_function"]]()
现在我想用setuptools来打包这个Python脚本,我有几个问题:
我应该怎么打包这个R支持代码?打包完成后,我该如何找到R文件的路径,以便可以调用它?
这段R代码依赖于几个R包。我该如何确保这些包已经安装?如果这些R包无法加载,我是否应该抛出一个提示性错误?
3 个回答
我应该怎么打包R支持的代码?打包完成后,我怎么找到R文件的路径,以便可以引用它?
要安装源文件,你需要在package_data
中以某种方式指定它们。你可以用和现在一样的方法找到它们的路径。
我的R代码依赖于几个R包。我怎么确保这些包都已安装?如果这些R包无法加载,我是不是应该抛出一个提示性错误?
你可以让setup.py
检查这些包是否存在(这有点像“配置工具的方法”),或者在无法加载时抛出某种异常。你也可以两者都做,这样如果你依赖的文件因为某种原因消失了,至少你会知道发生了什么。
想象一下,你是一个叫做setuptools的打包工具,想想作为程序员的你会希望做些什么。
- setuptools对R语言一无所知,也不知道它的文件结构,或者你的代码是如何使用这些文件的。
- 你的R解释器也不知道如何从Python的.egg文件中导入文件。
针对第一个问题,你有两个选择:
- 告诉setuptools直接包含一些额外的文件,而不管它们是什么。
- 教会setuptools关于R的知识,告诉它你的程序使用了哪些R文件,以及如何跟踪和包含它们的依赖关系。
第一个选项可以通过在setup()
中传递include_package_data = True
来实现,并在package_data
中提供要包含的文件的掩码(setuptools文档中的“包含数据文件”部分)。可以使用相对于包目录的路径。这些文件在运行时可以通过“资源管理API”以相同的相对路径访问(“在运行时访问数据文件”部分)。
第二个选项需要你在调用setup()
之前将你的代码添加到setuptools中。例如,你可以添加一个文件查找器,将相关的.R文件添加到find_packages()
的结果中。或者通过其他方式生成前面提到的文件列表。
对于第二个问题,最简单的方法是强制setuptools将包安装为一个目录,而不是.egg文件,这可以通过指定zip_safe = False
来实现。你也可以使用eager_resources
选项,这样可以按需提取一组资源(“自动资源提取”部分)。
至于安装第三方R包,可以参考R安装与管理 - 安装包中描述的可自动化的技术。
这个问题可能有点过时,但我今天遇到了同样的问题,想给@ivan_pozdeev建议的第一个问题解决方案提供更多细节,并给第二个问题提供一个新的解决方案。
1) 修改你的setup.py文件为:
from setuptools import setup, find_packages
setup(
...
# If any package contains *.r files, include them:
package_data={'': ['*.r', '*.R']},
include_package_data=True)
)
2) Conda现在越来越成为处理Python和R的包依赖的好选择。你可以创建一个环境(http://conda.pydata.org/docs/using/envs),下载你可能需要的所有R和Python包,然后生成一个environment.yml文件,这样任何人都可以复制你的环境。想了解更多信息,可以查看这个博客:https://www.continuum.io/content/conda-data-science