2010-09-14 19 views
23

讓我們採取以下項目佈局: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 

什麼給出了?

+0

一個更簡單的解決方案在此給出答案:http://stackoverflow.com/a/25375689/74632 – 2015-09-09 15:20:07

回答

18

在您的package_data中,您的'*' glob本身與package/dir匹配,並嘗試將該目錄複製爲文件,導致失敗。查找水珠,將不符合目錄package/dir,重寫你的setup.py沿着這些線路:

from distutils.core import setup 

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

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

鑑於你的榜樣,這只是改變'*''*.dat',雖然你可能需要改進你的水珠還不止這些,只要確保它不匹配'dir'

+6

啊。謝謝。你知道在指定「將所有東西遞歸地包含在這個包(在模塊之上)」中有更好的方法嗎?「 – Santa 2010-09-14 21:43:48

+2

您可能會通過使用MANIFEST.in文件逃脫,但不幸的是這比理想更困難(正如此搜索http://www.google.se/search?q=distutils+package_data+include+directory所示,很多人們問這個問題,並沒有多少人得到答案)。最全面的文檔是這樣的:http://docs.python.org/distutils/setupscript.html,但它不是很清楚寫(找到你的問題,我實際上已經陷入distutils源) – 2010-09-15 08:59:35

+1

雖然這似乎是該解決方案,distributils不能僅僅處理子目錄!這在Windows中正常工作,但在Linux中失敗。我有一個廣泛的子目錄嵌套,並且必須明確定義這將是真正的痛苦和更難以維護。 – BuvinJ 2016-03-15 18:44:47

4

您可以使用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' 
      ], 
     }, 
    ) 
0

我創建了一個功能,讓我的一切,我需要的文件

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 

並用,作爲arugment爲package_data

0

不明白爲什麼,但一些故障排除後,我意識到,重命名,在他們的名字有圓點的目錄解決了這個問題。例如。

chart.js-2.4.0 => chart_js-2_4_0 

注:我使用Python 2.7.10,setuptools的12.2

相關問題