如何在Python模块中封装支持R代码?

14 投票
3 回答
2263 浏览
提问于 2025-04-16 15:08

我正在尝试把一些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脚本,我有几个问题:

  1. 我应该怎么打包这个R支持代码?打包完成后,我该如何找到R文件的路径,以便可以调用它?

  2. 这段R代码依赖于几个R包。我该如何确保这些包已经安装?如果这些R包无法加载,我是否应该抛出一个提示性错误?

3 个回答

0

我应该怎么打包R支持的代码?打包完成后,我怎么找到R文件的路径,以便可以引用它?

要安装源文件,你需要在package_data中以某种方式指定它们。你可以用和现在一样的方法找到它们的路径。

我的R代码依赖于几个R包。我怎么确保这些包都已安装?如果这些R包无法加载,我是不是应该抛出一个提示性错误?

你可以让setup.py检查这些包是否存在(这有点像“配置工具的方法”),或者在无法加载时抛出某种异常。你也可以两者都做,这样如果你依赖的文件因为某种原因消失了,至少你会知道发生了什么。

3

想象一下,你是一个叫做setuptools的打包工具,想想作为程序员的你会希望做些什么。

  • setuptools对R语言一无所知,也不知道它的文件结构,或者你的代码是如何使用这些文件的。
  • 你的R解释器也不知道如何从Python的.egg文件中导入文件。

针对第一个问题,你有两个选择:

  1. 告诉setuptools直接包含一些额外的文件,而不管它们是什么。
  2. 教会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安装与管理 - 安装包中描述的可自动化的技术。

5

这个问题可能有点过时,但我今天遇到了同样的问题,想给@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

撰写回答