如何在python安装的软件包中包含文本文件? [英] How to include a text file in a python installed package?

查看:95
本文介绍了如何在python安装的软件包中包含文本文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个看起来像这样的python包:

I have created a python package that looks like this:

/command
    /command
        module.py
        __main__.py
    README.md
    setup.py
    file.txt

要安装我,请运行:

sudo python setup.py install

现在我打电话给

$ command

它显示此错误:

FileNotFoundError: [Errno 2] No such file or directory: '../file.txt'

大约包含模块 setup.py __ main __.py module.py

setup.py

import setuptools

setuptools.setup(
    name='command',
    ...
    entry_points={
        'console_scripts': [
            'command = command.__main__:main'
        ]
    }
)

__ main __.py

from . import module

def main():
    module.run('arg')

module.py

import shutil

# copy file.txt from command project into the directory where it is running
def run(arg):
    shutil.copyfile('../file.txt', './file.txt')

通过以下方式安装此软件包后:

After intalling this package via:

sudo python setup.py install

然后在命令行中调用程序

And calling the program at the command line

$ command

我收到下面的错误

FileNotFoundError: [Errno 2] No such file or directory: '../file.txt'

如何查看和使用属于已安装软件包的文件,但如何在运行该程序的环境中使用该文件?

How can I see and use a file that belongs to the installed package but I to use it in an environment where I am running that program?

这是您可以下载和测试的问题的简化版本:

https://github.com/mctrjalloh/project_initializer

推荐答案

因此,经过大量研究,我找到了解决此问题的方法以及它的工作方式.这有点令人困惑,其他所有stackoverflow答案都没有那么解释.我想在这里尝试:

So after a lot research i found the solution to this and how it works also. It's a little bit confusing, none of the other stackoverflow answers were really that explanatory. I want to try it here:

我已经为此目的创建了一个示例项目,以演示和测试解决方案.我提出了两种解决方案:一种使用setup()函数的 data_files 参数,另一种使用我最喜欢的 package_data 参数.

I have made a sample project for that only purpose to demostrate and test the solution. I have come up with two solutions: one using the data_files argument of the setup() function and the other using the package_data argument which i preferred the most.

这是您可以下载和测试的github存储库的链接

要在安装后使用它,请运行

To use it after installation run

proj init <some-name>

但简单来说,每种方法都有最重要的模块.

But to be brief there are the most important modules for each method.

使用数据文件 =参数方法:

USING data_files= ARGUMENT METHOD:

项目结构:

project_initializer
    project_initializer
        __init__.py
        __main__.py
        init.py
    README.md
    setup.py

setup.py

import setuptools
import os
import sys


PROJECT_NAME = "project_initializer"
DATA_DIR = os.path.join(
    sys.prefix, "local/lib/python3.6/dist-packages", PROJECT_NAME)


setuptools.setup(
    name='project_initializer',
    version='0.1.0',
    packages=setuptools.find_packages(),
    install_requires=[
        'docopt'
    ],
    data_files=[         # is the important part
        (DATA_DIR, [
            "README.md",
            ".gitignore"
        ])               
    ],
    entry_points={
        'console_scripts': [
            'proj = project_initializer.__main__:main'
        ]
    }
)

init.py

import subprocess
import os
import shutil
import sys

"""Create a new project and initialize it with a .gitignore file
@params project: name of a project to be initialized
effects:
    /project
        README.md
    README.md in the created project directory must be the same as the README.md in THIS directory 
"""

PROJECT_NAME = "project_initializer"
DATA_DIR = os.path.join(
    sys.prefix, "local/lib/python3.6/dist-packages", PROJECT_NAME)


def run(project):
    os.mkdir(project)
    shutil.copyfile(os.path.join(DATA_DIR, "README.md"),
                    f"{project}/README.md")  # problem solved


if __name__ == '__main__':
    run("hello-world")

使用 package_data = 参数方法(我更喜欢)

USING package_data= ARGUMENT METHOD (which i preferred)

项目结构:

project_initializer
    project_initializer
        data/
            README.md  # the file we want to copy
        __init__.py
        __main__.py
        init.py
    README.md
    setup.py

setup.py

import setuptools


setuptools.setup(
    name='project_initializer',
    version='0.1.0',
    packages=setuptools.find_packages(),
    package_dir={'project_initializer': 'project_initializer'}, # are the ... 
    package_data={'project_initializer': [ # ... important parameters
        'data/README.md', 'data/.gitignore']},
    install_requires=[
        'docopt'
    ],
    entry_points={
        'console_scripts': [
            'proj = project_initializer.__main__:main'
        ]
    }
)

init.py

import subprocess
import os
import shutil
import sys

PROJECT_DIR = os.path.dirname(__file__)

"""Create a new project and initialize it with a .gitignore file
@params project: name of a project to be initialized
effects:
    /project
        .gitignore
    .gitignore in the created project directory must be the same as the gitignore in THIS directory 
"""


def run(project):
    os.mkdir(project)
    shutil.copyfile(os.path.join(PROJECT_DIR, 'data/README.md'),
                    f"{project}/README.md")  # problem solved


if __name__ == '__main__':
    run("hello-world")

之所以我选择最后一种方法,是因为您不必在setup.py模块中导入任何内容,这可能是一种不好的做法.我猜没有什么应该导入setup.py文件中,因为它是主程序包的外部文件.

The reason why i prefer this last method is because you have not to import anything in the setup.py module which could be presumably a bad practice. I guess nothing should be imported in the setup.py file since it is an external file to the main package.

有关这两个参数之间的区别的更详细说明,请查看python文档

For more detailed explanation of what are the differences between the two arguments check out the python docs

使用 data_files = 参数

使用 package_data = 参数

这篇关于如何在python安装的软件包中包含文本文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆