Erreur Python distutils: "[directory] ...n'existe pas ou n'est pas un fichier régulier"
Prenons la mise en page de projet suivante:
$ ls -R .
.:
package setup.py
./package:
__init__.py dir file.dat module.py
./package/dir:
tool1.dat tool2.dat
Et le contenu suivant pour setup.py
:
$ cat setup.py
from distutils.core import setup
setup(name='pyproj',
version='0.1',
packages=[
'package',
],
package_data={
'package': [
'*',
'dir/*',
],
},
)
Comme vous pouvez le voir, je veux inclure tous les fichiers non-Python dans les répertoires package/
et package/dir/
. Cependant, l'exécution de setup.py install
provoquerait l'erreur suivante:
$ 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
Qu'est-ce qui donne?
4 réponses
Dans votre package_data
, Votre '*'
glob correspondra à package/dir
lui-même et tentera de copier ce répertoire en tant que Fichier, ce qui entraînera un échec. Trouvez un glob qui ne correspond pas au répertoire package/dir
, en réécrivant votre setup.py
selon ces lignes:
from distutils.core import setup
setup(name='pyproj',
version='0.1',
packages=[
'package',
],
package_data={
'package': [
'*.dat',
'dir/*'
],
},
)
Compte tenu de votre exemple, cela change simplement '*'
en '*.dat'
, bien que vous ayez probablement besoin d'affiner votre glob plus que cela, assurez-vous simplement qu'il ne correspondra pas à 'dir'
Vous pouvez utiliser Distribuer au lieu de distutils. Cela fonctionne fondamentalement de la même manière (pour la plupart, vous n'aurez pas à changer votre setup.py) et il vous donne l'option 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'
],
},
)
J'ai créé une fonction qui me donne tous les fichiers dont j'ai besoin
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
Et utilisé comme roquette pour package_data
Pas tout à fait sûr pourquoi, mais après quelques dépannages, j'ai réalisé que renommer les répertoires qui avaient des points dans leurs noms résolvait le problème. Par exemple
chart.js-2.4.0 => chart_js-2_4_0
Note: j'utilise Python 2.7.10, setuptools 12.2