12 python packaging distutils python-module setuptools
我正在尝试将数据文件包含在我的包中的distutils中,然后使用相对路径引用它们(参见http://docs.python.org/distutils/setupscript.html#distutils-additional-files)
我的目标结构是:
myproject/
mycode.py
data/
file1.dat
Run Code Online (Sandbox Code Playgroud)
代码mycode.py,实际上是包中的脚本.它依赖于访问data/file1.dat,使用相对路径引用它.在setup.py,我有:
setup(
...
scripts = "myproject/mycode.py"
data_files = [('data', 'myproject/data/file1.dat')]
)
Run Code Online (Sandbox Code Playgroud)
假设用户现在使用:
python setup.py --prefix=/home/user/
Run Code Online (Sandbox Code Playgroud)
然后mycode.py会出现在某些地方/home/user/bin/.但是data/file1.dat现在已经破坏了引用,因为脚本存在于数据的其他地方.
我怎样才能找到mycode.py绝对路径myproject/data/file1.dat,所以我可以根据用户安装包的位置正确引用它?
编辑
当我安装这个prefix=/home/user/,我得到data/file1.dat创造了/home/user/这正是我想要的,唯一缺少的部分是如何检索,只给出一个相对路径,不知道在用户安装的程序包的绝对路径该文件编程.当我尝试使用package_data而不是data_files,它不起作用 - 我只是不在data/file1.dat任何地方创建,即使我删除我的MANIFEST文件.
我已经阅读了目前关于这个看似非常普遍的问题的所有讨论.然而,所有提出的解决方案都没有处理我上面的情况,其中需要访问的代码data_files是脚本,其位置可能会根据--prefix参数而改变setup.py.我能想到的解决这个问题的唯一黑客是添加数据文件scripts=中setup(),如:
setup(
...
scripts = ["myproject/mycode.py", "myproject/data/file1.data"]
)
Run Code Online (Sandbox Code Playgroud)
这是一个可怕的黑客,但它是我能想到的唯一方法,以确保file1.data将与脚本定义在同一个地方scripts=,因为我找不到任何平台独立和安装敏感的API来恢复data_files用户运行后的位置setup.py install(可能与--prefix=args).
Jas*_*mbs 11
我认为混淆源于脚本的使用.脚本应该引用一个可运行的可执行文件,可能是与您的软件包相关的实用程序脚本,也可能是您的软件包功能的入口点.在任何一种情况下,您都应该期望任何脚本不会与包的其余部分一起安装.这种期望主要是由于包被认为是库(并安装到lib目录)的惯例,而脚本被认为是可执行文件(并安装到bin或Scripts目录).此外,数据文件既不是可执行文件也不是库,而是完全独立的.
因此,从脚本中,您需要确定数据文件的位置.根据Python文档,
如果directory是相对路径,则相对于安装前缀进行解释.
因此,您应该在mycode脚本中编写类似以下内容的内容来查找数据文件:
import sys
import os
def my_func():
with open(os.path.join(sys.prefix, 'data', 'file1.dat')) as f:
print(next(f))
if __name__ == '__main__':
my_func()
Run Code Online (Sandbox Code Playgroud)
如果你对代码和数据没有捆绑在一起的方式不满意(我不会),那么我会重构你的包,这样你就有了一个实际的Python包(和模块)并使用packages =和package_data =将数据注入包中,然后创建一个调用包中模块的简单脚本.
我通过创建这个树来做到这一点:
.
? setup.py
?
????myproject
? ? mycode.py
? ? __init__.py
? ?
? ????data
? file1.dat
?
????scripts
run-my-code.py
Run Code Online (Sandbox Code Playgroud)
使用setup.py:
from distutils.core import setup
setup(
name='myproject',
version='1.0',
scripts=['scripts/run-my-code.py'],
packages=['myproject'],
package_data = {
'myproject': ['data/file1.dat'],
},
)
Run Code Online (Sandbox Code Playgroud)
run-my-code.py简单地说:
from myproject import mycode
mycode.my_func()
Run Code Online (Sandbox Code Playgroud)
__init__ 是空的,mycode.py看起来像:
import os
here = os.path.dirname(__file__)
def my_func():
with open(os.path.join(here, 'data', 'file1.dat')) as f:
print(next(f))
Run Code Online (Sandbox Code Playgroud)
后一种方法将数据和代码捆绑在一起(在site-packages/myproject中),并且只将脚本安装在不同的位置(因此它显示在$ PATH中).
您应该能够使用pkg_resources.resource_filename来获取data_files中文件的文件名。