如何使用可以访问 R 脚本的 pip 安装包
How to install package with pip that has access to an R script
问题
我需要创建一个 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 脚本的优点。有关更多信息,我正在创建一个更复杂的 python 包,类似于 this,它需要在某些时候调用 R,这是用 subprocess.run
完成的,但是我相信那是不可能的这个问题的范围
Python=='3.5.2'
setuptools=='27.2.0'
pip=='10.0.1
这是 "editable" 安装的正常行为。来自 setuptools docs:
In addition, the develop command creates wrapper scripts in the target script directory that will run your in-development scripts after ensuring that all your install_requires packages are available on sys.path.
pip install -e
与 python setup.py develop
并不完全相同,但旨在非常接近。我相信 implementation 是 python setup.py develop
.
的薄包装
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__
进行操作。
发生这种情况是因为您的 R 脚本与 Python 完全不同。
如果您要放置一些导致语法错误的 R 代码,例如前导 .
或 $
或 foo[[0]]
的任何用法,您会发现 setuptools(但实际上distutils+easy_install) 不生成 develop
包装器。
可以找到控制脚本包装器的源代码here. It tests with is_python_script
which calls is_python
。这反过来只是编译文件。成功编译 returns True 并导致 easy_install 生成包装脚本,不成功编译 returns False 并且文件只是逐字复制(这就是你想要的)。
问题
我需要创建一个 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 脚本的优点。有关更多信息,我正在创建一个更复杂的 python 包,类似于 this,它需要在某些时候调用 R,这是用 subprocess.run
完成的,但是我相信那是不可能的这个问题的范围
Python=='3.5.2'
setuptools=='27.2.0'
pip=='10.0.1
这是 "editable" 安装的正常行为。来自 setuptools docs:
In addition, the develop command creates wrapper scripts in the target script directory that will run your in-development scripts after ensuring that all your install_requires packages are available on sys.path.
pip install -e
与 python setup.py develop
并不完全相同,但旨在非常接近。我相信 implementation 是 python setup.py develop
.
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__
进行操作。
发生这种情况是因为您的 R 脚本与 Python 完全不同。
如果您要放置一些导致语法错误的 R 代码,例如前导 .
或 $
或 foo[[0]]
的任何用法,您会发现 setuptools(但实际上distutils+easy_install) 不生成 develop
包装器。
可以找到控制脚本包装器的源代码here. It tests with is_python_script
which calls is_python
。这反过来只是编译文件。成功编译 returns True 并导致 easy_install 生成包装脚本,不成功编译 returns False 并且文件只是逐字复制(这就是你想要的)。