我需要创建一个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
答案 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.py
。 foo.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?。它使用调用here的is_python_script
进行测试。这反过来只是编译文件。成功的编译返回True并导致easy_install创建包装器脚本,不成功的返回False,文件只是逐字复制(这是你想要的)。
答案 2 :(得分:0)
这是"可编辑"的正常行为。安装。来自setuptools docs:
此外,develop命令在目标脚本目录中创建包装脚本,在确保所有install_requires包在sys.path上可用之后运行开发中脚本。
pip install -e
与python setup.py develop
完全相同,但它的目的非常接近。我相信implementation是python setup.py develop
周围的薄包装。