Подтвердить что ты не робот

Ошибка Python distutils: "[каталог]... не существует или нет обычного файла"

Возьмем следующий макет проекта:

$ ls -R .
.:
package  setup.py

./package:
__init__.py  dir  file.dat  module.py

./package/dir:
tool1.dat  tool2.dat

И следующий контент для setup.py:

$ cat setup.py 
from distutils.core import setup


setup(name='pyproj',
      version='0.1',

      packages=[
          'package',
      ],
      package_data={
          'package': [
              '*',
              'dir/*',
          ],
      },
     )

Как вы можете видеть, я хочу включить все файлы, отличные от Python, в каталоги package/ и package/dir/. Однако запуск setup.py install приведет к следующей ошибке:

$ python setup.py install
running install
running build
running build_py
creating build
creating build/lib
creating build/lib/package
copying package/module.py -> build/lib/package
copying package/__init__.py -> build/lib/package
error: can't copy 'package/dir': doesn't exist or not a regular file

Что дает?

4b9b3361

Ответ 1

В package_data ваш твист '*' будет соответствовать самому package/dir и попытаться скопировать этот каталог в файл, что приведет к ошибке. Найдите glob, который не будет соответствовать каталогу package/dir, переписав ваш setup.py в следующих строках:

from distutils.core import setup

setup(name='pyproj',
      version='0.1',

      packages=[
          'package',
      ],
      package_data={
          'package': [
              '*.dat',
              'dir/*'
          ],
      },
     )

Учитывая ваш пример, просто изменив '*' на '*.dat', хотя вам, вероятно, понадобится уточнить ваш glob больше, чем это, просто убедитесь, что он не будет соответствовать 'dir'

Ответ 2

Вы можете использовать Distribute вместо distutils. Он работает в основном одинаково (по большей части вам не придется менять setup.py), и он дает вам опцию exclude_package_data:

from distribute_setup import use_setuptools
use_setuptools()

from setuptools import setup

setup(name='pyproj',
      version='0.1',

      packages=[
          'package',
      ],
      package_data={
          'package': [
              '*.dat',
              'dir/*'
          ],
      },
      exclude_package_data={
          'package': [
              'dir'
          ],
      },
     )

Ответ 3

Я создал функцию, которая дает мне все файлы, которые мне нужны

def find_files(directory, strip):
  """
  Using glob patterns in ``package_data`` that matches a directory can
  result in setuptools trying to install that directory as a file and
  the installation to fail.

  This function walks over the contents of *directory* and returns a list
  of only filenames found. The filenames will be stripped of the *strip*
  directory part.
  """

  result = []
  for root, dirs, files in os.walk(directory):
    for filename in files:
      filename = os.path.join(root, filename)
      result.append(os.path.relpath(filename, strip))
  return result

И использовал это как выражение для package_data

Ответ 4

Не совсем понятно, почему, но после некоторого устранения неполадок я понял, что переименование каталогов с точками в их именах решило проблему. Например.

chart.js-2.4.0 => chart_js-2_4_0

Примечание. Я использую Python 2.7.10, SetupTools 12.2