2010-09-14 13 views
23

Tomemos la siguiente distribución del proyecto:Python distutils de error: "[directorio] ... no existe o no es un archivo normal"

$ ls -R . 
.: 
package setup.py 

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

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

Y el siguiente contenido para setup.py:

$ cat setup.py 
from distutils.core import setup 


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

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

Como puede ver, quiero incluir todos los archivos que no sean de Python en los directorios package/ y package/dir/. Sin embargo, ejecutar setup.py install elevaría el siguiente error:

$ 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 

Lo que da?

+0

Una solución mucho más simple se da en esta respuesta: http://stackoverflow.com/a/25375689/74632 –

Respuesta

18

En su package_data, su '*' pegote coincidirá package/dir sí mismo, y tratar de copiar ese directorio como un archivo, lo que resulta en un fracaso. Encontrar un pegote que no coincida con el directorio package/dir, reescribiendo su setup.py largo de estas líneas:

from distutils.core import setup 

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

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

dado tu ejemplo, eso es sólo el cambio de '*' a '*.dat', a pesar de lo que probablemente necesita para afinar su pegote más que eso , solo asegúrese de que no concuerde con 'dir'

+6

Ah. Gracias. ¿Sabes si hay una forma más elegante de especificar "incluir todo, recursivamente, en este paquete (en la parte superior de los módulos)"? – Santa

+2

Puede escaparse utilizando un archivo MANIFEST.in, pero desafortunadamente es más difícil que ideal (como muestra esta búsqueda http://www.google.se/search?q=distutils+package_data+include+directory, una gran cantidad de las personas hacen esta pregunta, y no muchas obtienen respuestas). El documento más completo es este: http://docs.python.org/distutils/setupscript.html, pero no está escrito con mucha claridad (para encontrar su problema, en realidad pdb'd en la fuente de distutils) –

+1

Aunque parece ser la solución, ¡es horrible que distributils no pueda manejar subdirectorios de la caja! Esto funciona bien en Windows, pero falla en Linux. Tengo un anidamiento extenso de subdirectorios, y tener que definir explícitamente que va a ser un verdadero dolor y ser más difícil de mantener. – BuvinJ

4

Puede usar Distribute en lugar de distutils. Funciona básicamente el mismo (en su mayor parte, usted no tendrá que cambiar su setup.py) y se le da la opción 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' 
      ], 
     }, 
    ) 
0

creé una función que me da todos los archivos que deba

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 

utilizados y de que a medida que arugment para package_data

0

No estoy seguro de por qué, pero después de algunos ajustes me di cuenta que el cambio de nombre de los directorios que tenían puntos en sus nombres resolvió el problema. P.ej.

chart.js-2.4.0 => chart_js-2_4_0 

Nota: Estoy usando Python 2.7.10, setuptools 12.2

Cuestiones relacionadas