MANIFEST.in이 "python setup.py install"에서 무시 됨-설치된 데이터 파일이 없습니까?


89

코드가 아닌 항목이 제거 된 내 제거 된 setup.py 스크립트는 다음과 같습니다.

#!/usr/bin/env python

from distutils.core import setup
from whyteboard.misc import meta


setup(
    name = 'Whyteboard',
    version = meta.version,

    packages = ['whyteboard', 'whyteboard.gui', 'whyteboard.lib', 'whyteboard.lib.pubsub',
                'whyteboard.lib.pubsub.core', 'whyteboard.lib.pubsub.utils', 'whyteboard.misc'],

    py_modules = ['whyteboard'],
    scripts = ['whyteboard.py'],
)

MANIFEST.in :

include *.txt
include whyteboard-help/*.*
recursive-include locale *.mo
recursive-include images *.png

"python setup.py install sdist"를 실행하면 "whyteboard-0.41"루트 폴더가있는 멋진 .tar.gz와 locale / images / 및 whyteboard-help / 폴더가 내부에 있습니다. 여기에는 whyteboard 소스 패키지 내부에서 내 프로그램을 시작하는 whyteboard.py 스크립트도 있습니다.

그래서:

whyteboard/
 ├── locale/
 ├── images
 ├── whyteboard-help/
 ├── whyteboard/
 │  ├── __init__.py
 │  └── other packages etc
 ├── whyteboard.py
 ├── README
 ├── setup.py
 └── CHANGELOG

이것은 내 프로그램의 소스를 반영하고 모든 것이 올바른 방법입니다.

그러나 "python setup.py install"을 실행하면 데이터 파일이 작성되지 않습니다. "whyteboard"소스 패키지 만 작성되고 whyteboard.py는 /usr/local/lib/python2.6/dist-packages/에 있습니다. .

이상적으로는 .tar.gz 파일에서 생성 된 것과 동일한 디렉토리 구조를 dist-packages에서 생성하고 싶습니다. 이것이 내 프로그램이 리소스를 찾을 것으로 예상하는 방식이기 때문입니다.

이 디렉토리 구조를 만들기 위해 "설치"를하려면 어떻게해야합니까? 내가 알 수있는 한 내 매니페스트 파일을 무시하는 것 같습니다.


답변:


30

Ned의 답변 (핵심 문제에 해당)에 추가 된 몇 가지 메모 :

Distutils는 프로젝트 별 하위 디렉토리 site-packages(또는 dist-packagesDebian / Ubuntu)에 Python 패키지 및 모듈을 설치하지 않습니다. 보시다시피에 직접 설치됩니다 site-packages. 따라서 whyteboard-xxsdist 의 포함 디렉토리는 최종 설치된 양식에 존재하지 않습니다.

이것의 한 가지 의미는 data_files파일 / 디렉터리가 site-packages포함 된 whyteboard디렉터리가 아닌 전역 디렉터리에 직접 설치되기 때문에 해당 파일 / 디렉터리가 속한 프로젝트를 명확히하는 방식으로 이름을 지정하는 데주의해야한다는 것 입니다.

또는 대신 패키지 의 데이터 package_data를 만들 수 있습니다 whyteboard(즉, 패키지 내부에 있어야 함, 즉 옆에 있어야 함 __init__.py). 그러면 문제가되지 않습니다.

마지막으로, .NET에 whyteboard.py모듈 py_moduleswhyteboard/__init__.py패키지를 모두 포함하는 것은 의미가 없습니다 packages. 둘은 상호 배타적이며 둘 다 whyteboard.py있는 경우 동일한 이름의 패키지를 선호하는 가져 오기에서 모듈이 무시됩니다.

whyteboard.py스크립트이고 가져올 의도가없는 경우 스크립트 옵션을 사용 하고에서 제거해야합니다 py_modules.


1
운이 없었어. 패키지 데이터가 있다는 생각이 마음에 들지 않습니다. 저에게는 이러한 리소스가 소스 디렉터리 외부에있는 것이 더 합리적입니다. 또한 프로그램 이름 앞에 디렉토리 이름을 붙이는 것을 좋아하지 않습니다 (이미 도움말 파일에 대해 수행했지만). 흠 ..
Steven Sproat

67

MANIFEST.in소스 배포에 포함 할 파일을 Distutils에 알려 주지만 설치된 파일에 직접적인 영향을주지는 않습니다. 이를 위해서는 setup.py일반적으로 패키지 데이터 또는 추가 파일 로 적절한 파일을 파일에 포함해야 합니다 .


패키지 데이터 목록을 추가하려고했지만 지정한 파일이 사용되지 않았습니다. 패키지의 전체 설치와 관련하여 파일의 위치가 설치되었는지 확실하지 않았습니다. 어쨌든, 내가 예상 한 올바른 디렉토리 구조에 파일을 작성하지 못했습니다.
Steven Sproat

이 답변에 링크 된 설명서는 data_files 및 package_data가 설치된 위치에 대해 필요한 모든 정보를 제공합니다. 이러한 옵션이 작동하지 않으면 시도한 정확한 구문, 결과 및 예상 한 내용으로 질문을 업데이트하십시오.
Carl Meyer

4
이것은 나를 위해 작동합니다 : setup.py의 data_packages 안에 내 MANIFEST.in 항목을 복제하면 모든 것이 작동합니다. 고마워 Ned-나는이 점을 수년간 이해하지 못했습니다. 이제 내 distutils / setuptools / distribute 경험이 더 의미가 있기를 바랍니다.
Jonathan Hartley 2011 년

7
패키지에 설치되지 않는 파일을 포함 할 수 있다는이 디자인이 의미가 있습니까? 언제 사용됩니까?
Roger Dahl

27

내 이유를 알아낼 수 없었다 MANIFEST.in내가 실행할 때 파일이 무시되고 있었다 python setup.py install- 밝혀 include_package_data=True문제로 해결할 수있는 문제입니다. 이 package_data옵션은 실제로 필요하지 않습니다.


좋은 캐치, 왜 include_package_data=True기본값이 아닌가?
liang

9

setuptools를 사용해야합니다.

#!/usr/bin/env python

from setuptools import setup, find_packages
from whyteboard.misc import meta


setup(
  name = 'Whyteboard',
  version = meta.version,

  packages = find_packages(),
  include_package_data=True,

  py_modules = ['whyteboard'],
  scripts = ['whyteboard.py'],
)

이것은 실제로 MANIFEST 파일을 사용하여 작업을 수행하는 것이 아니라 필요한 모든 파일을 포함합니다.


이것은 setuptools 로 나를 위해 일했습니다 . 데비안 패키지를 빌드했는데 package_data사전에 나열된 glade 파일이를 추가 한 후에 만 ​​올바른 위치에 나타납니다 include_package_data=Tru.
mlt jul

8

Mac OSX에서 python 2.6.1을 실행하면 setup.py 에서 data_files 매개 변수를 사용하는 것 외에는 전혀 운이 없었습니다 . MANIFEST.in을 사용하는 모든 것은 dist 패키지에 파일이 포함되었지만 설치되지는 않았습니다. 다른 패키지를 확인한 결과 실제로 추가 파일을 지정하기 위해 data_files를 사용하고있었습니다.

디렉토리 트리의 모든 파일을 열거하는 데 도움이되는 짧은 함수를 만들었습니다.

(target_dir, [file list]) data_files가 예상하는 형식 :

def gen_data_files(*dirs):
    results = []

    for src_dir in dirs:
        for root,dirs,files in os.walk(src_dir):
            results.append((root, map(lambda f:root + "/" + f, files)))
    return results

이제 설정 호출에서 이것을 호출 할 수 있습니다.

setup(... data_files = gen_data_files("docs", "lib") ...

그리고 그 나무의 모든 것이 설치됩니다.


11
이것은 훌륭하지만 어디에 설치됩니까? 나를 위해 "pip install"을 사용할 때 내 data_files는 내 virtualenv의 루트 (즉, 모든 virtualenv의 패키지가 공유하는 단일 디렉토리)로 이동합니다. "setup.py install"을 사용하는 경우 내 data_files는 "site- packages / <mypackage> .egg / ". 파일이 런타임에 필요한 데이터 인 경우 두 경우 모두 내 코드가 이러한 파일을 찾는 것이 사소한 일이 아니며 물론 런타임에 두 디렉터리를 모두 검색해야합니다. 파일이 내 LICENSE 파일이면 내 사용자가 내 소스에서 LICENSE로 가져 오는 것이 결코 사소한 일이 아닙니다. 어찌할 바를 모르는.
Jonathan Hartley

3

최소 게시 실행 가능 예제

핵심 요점 : MANIFEST.in나 에게만 효과가 있었지만 package_data그렇지 않았습니다.

Ubuntu 19.10, Python 3.7.5, wheel == 0.32.3, setuptools == 41.1.0, twine == 3.1.1에서 테스트되었습니다.

최종 사용자가 https://pypi.org/project/python-sample-package-with-data/ 에서 패키지를 사용하는 방법 :

python3 -m pip install --user python-sample-package-with-data
python-sample-package-with-data

예상 출력 :

hello data

관리자가 게시하는 방법 :

# One time setup.
python3 -m pip install --user setuptools wheel twine

# Every time you want to publish.
python setup.py sdist bdist_wheel
twine upload dist/*
rm -rf build dist *.egg-info

실제 파일 :

MANIFEST.in

# Or else pip install cannot find README.md on the setup.py under certain conditions.
include README.md

# This actually adds the data file.
include python_sample_package_with_data/mydata.txt

python-sample-package-with-data

#!/usr/bin/env python3

import python_sample_package_with_data

print(python_sample_package_with_data.get_data(), end='')

python_sample_package_with_data / __ init__.py

try:
    import importlib.resources as importlib_resources
except ImportError:
    # In PY<3.7 fall-back to backported `importlib_resources`.
    import importlib_resources

def get_data():
    return importlib_resources.read_text(__name__, 'mydata.txt')

python_sample_package_with_data / mydata.txt

hello data

setup.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from setuptools import setup, find_packages

from os import path
this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md')) as f:
    long_description = f.read()

setup(
    name='python-sample-package-with-data',
    version='0.0.3',
    description='My short description',
    long_description=long_description,
    long_description_content_type='text/markdown',
    url='https://github.com/cirosantilli/python-sample-package-with-data',
    author='Ciro Santilli',
    author_email='ciro.santilli.contact@gmail.com',
    packages=find_packages(),
    include_package_data=True,
    scripts=['python-sample-package-with-data'],
)

서지:

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.