如何安装包含有权访问R脚本的pip的包

时间:2018-05-16 19:31:14

标签: python r pip setuptools conda

问题

我需要创建一个python包,它可以访问R脚本并使其可以安装pip

设置:

我的包结构如下

foo/  
  setup.py  
  foo/
    foo.R

setup.py的内容是:

from setuptools import setup, find_packages

setup(
    name='foo',
    packages=find_packages(),
    scripts=['foo/foo.R'],
    zip_safe=False,
)

并且foo.R的内容是:

#!/usr/bin/env Rscript

R.version

我正在安装此软件包:
pip install -e .

当我查看安装的R脚本时,它不再是R脚本,因此在调用它时它将作为python运行,因此失败

$ cat $(which foo.R)查看文件的内容

我期待的是:

#!/usr/bin/env Rscript

R.version

我得到了什么:

#!/Users/jc33/miniconda3/bin/python
# EASY-INSTALL-DEV-SCRIPT: 'foo==0.0.0','foo.R'
__requires__ = 'foo==0.0.0'
__import__('pkg_resources').require('foo==0.0.0')
__file__ = '/Users/jc33/Desktop/foo/foo/foo.R'
exec(compile(open(__file__).read(), __file__, 'exec'))

附加范围

这是一个非常人为的例子,它的唯一目的是找到解决方案,而不是讨论使用setuptools定位R脚本的优点。有关更多信息,我正在创建一个类似于this的更复杂的python包,需要在某个时刻调用R,这是用subprocess.run完成的,但是我认为这超出了这个问题的范围

Python=='3.5.2'
setuptools=='27.2.0'
pip=='10.0.1

3 个答案:

答案 0 :(得分:1)

scripts适用于 Python 脚本。如果你想安装一些东西 根本不是Python代码,您需要将其视为数据。在 setuptools它被称为package_data

setup(
    name='foo',
    packages=find_packages(),
    package_data={
        'foo': ['foo.R'],
    },
    zip_safe=False,
)

该文件将安装为foo/foo.R,您可以在foo/中的模块中找到它,让我们说foo/foo.pyfoo.py中的第一件事是查找其目录,然后调用foo.R

import os, subprocess
foo_dir = os.path.dirname(__file__)
subprocess.check_call(['r', os.path.join(foo_dir, 'foo.R')])

PS。请注意,代码应该位于foo/目录中的模块中。对于不同的目录,它必须以不同的方式使用__file__进行操作。

答案 1 :(得分:1)

这种情况正在发生,因为你的R脚本与Python不同。

如果您要放置导致语法错误的一些R代码,例如前导.$foo[[0]]的任何用法,您会发现setuptools(但实际上是distutils + easy_install)不会生成develop包装器。

可以找到控制脚本包装器的源What is the purpose of self?。它使用调用hereis_python_script进行测试。这反过来只是编译文件。成功的编译返回True并导致easy_install创建包装器脚本,不成功的返回False,文件只是逐字复制(这是你想要的)。

答案 2 :(得分:0)

这是"可编辑"的正常行为。安装。来自setuptools docs

  

此外,develop命令在目标脚本目录中创建包装脚本,在确保所有install_requires包在sys.path上可用之后运行开发中脚本。

pip install -epython setup.py develop完全相同,但它的目的非常接近。我相信implementationpython setup.py develop周围的薄包装。