2015-12-10 10 views
3

我已经创建了一个名为clearplot的包裹在matplotlib中。我还创建了一个很好的字体,我想用我的包进行分发。我咨询了Python Packaging用户指南的this section,并确定我应该使用data_files关键字。我选择了data_files而不是package_data,因为我需要将该字体安装在我的包的之外的matplotlib目录中,该目录为如何使用我的Python包分发字体?

这是我的第一次,有缺陷,尝试在setup.py文件:

from distutils.core import setup 
import os, sys 
import matplotlib as mpl 

#Find where matplotlib stores its True Type fonts 
mpl_data_dir = os.path.dirname(mpl.matplotlib_fname()) 
mpl_ttf_dir = os.path.join(mpl_data_dir, 'fonts', 'ttf') 

setup(
    ...(edited for brevity)... 
    install_requires = ['matplotlib >= 1.4.0, !=1.4.3', 'numpy >= 1.6'], 
    data_files = [ 
     (mpl_ttf_dir, ['./font_files/TeXGyreHeros-txfonts/TeXGyreHerosTXfonts-Regular.ttf']), 
     (mpl_ttf_dir, ['./font_files/TeXGyreHeros-txfonts/TeXGyreHerosTXfonts-Italic.ttf'])] 
) 

#Try to delete matplotlib's fontList cache 
mpl_cache_dir = mpl.get_cachedir() 
mpl_cache_dir_ls = os.listdir(mpl_cache_dir) 
if 'fontList.cache' in mpl_cache_dir_ls: 
    fontList_path = os.path.join(mpl_cache_dir, 'fontList.cache') 
    os.remove(fontList_path) 

有两个问题与此setup.py

  1. 我尝试导入matplotlib setup()有机会安装前它。这是一个明显的booboo,但我需要知道在运行setup()之前mpl_ttf_dir
  2. 如提到的here,车轮分布不支持绝对路径data_files。我不认为这会是一个问题,因为我认为我只会使用sdist发行版。 (sdists确实允许绝对路径)。然后我发现pip 7.0(及更高版本)将所有包转换为轮子分布,即使分布最初是作为sdist创建的。

我对第二个问题非常恼火,但是从那以后,我发现绝对路径不好,因为它们不适用于virtualenv。因此,我现在愿意改变我的方法,但我该怎么做?

我唯一的想法是首先将字体分配为package_data,然后使用os模块将字体移动到适当的位置。这是一个犹太教的方法吗?

回答

2

感谢@ benjaoming的回答和this blog post,这里是我想出了:

from setuptools import setup 
from setuptools.command.install import install 
import warnings 

#Set up the machinery to install custom fonts. Subclass the setup tools install 
#class in order to run custom commands during installation. 
class move_ttf(install): 
    def run(self): 
     """ 
     Performs the usual install process and then copies the True Type fonts 
     that come with clearplot into matplotlib's True Type font directory, 
     and deletes the matplotlib fontList.cache 
     """ 
     #Perform the usual install process 
     install.run(self) 
     #Try to install custom fonts 
     try: 
      import os, shutil 
      import matplotlib as mpl 
      import clearplot as cp 

      #Find where matplotlib stores its True Type fonts 
      mpl_data_dir = os.path.dirname(mpl.matplotlib_fname()) 
      mpl_ttf_dir = os.path.join(mpl_data_dir, 'fonts', 'ttf') 

      #Copy the font files to matplotlib's True Type font directory 
      #(I originally tried to move the font files instead of copy them, 
      #but it did not seem to work, so I gave up.) 
      cp_ttf_dir = os.path.join(os.path.dirname(cp.__file__), 'true_type_fonts') 
      for file_name in os.listdir(cp_ttf_dir): 
       if file_name[-4:] == '.ttf': 
        old_path = os.path.join(cp_ttf_dir, file_name) 
        new_path = os.path.join(mpl_ttf_dir, file_name) 
        shutil.copyfile(old_path, new_path) 
        print "Copying " + old_path + " -> " + new_path 

      #Try to delete matplotlib's fontList cache 
      mpl_cache_dir = mpl.get_cachedir() 
      mpl_cache_dir_ls = os.listdir(mpl_cache_dir) 
      if 'fontList.cache' in mpl_cache_dir_ls: 
       fontList_path = os.path.join(mpl_cache_dir, 'fontList.cache') 
       os.remove(fontList_path) 
       print "Deleted the matplotlib fontList.cache" 
     except: 
      warnings.warn("WARNING: An issue occured while installing the custom fonts for clearplot.") 

setup(... 
    #Specify the dependencies and versions 
    install_requires = ['matplotlib >= 1.4.0, !=1.4.3', 'numpy >= 1.6'], 
    #Specify any non-python files to be distributed with the package 
    package_data = {'' : ['color_maps/*.csv', 'true_type_fonts/*.ttf']}, 
    #Specify the custom install class 
    cmdclass={'install' : move_ttf} 
) 

这解决了这两个问题#1(它安装matplotlib它导入之前)和问题#2(它的工作原理轮)。

1

我唯一的想法是首先将字体分配为package_data,然后使用os模块将字体移动到适当的位置。这是一个犹太教的方法吗?

我会考虑这样做。我知道你的软件包可能不是virtualenvs的明显候选者,但考虑到python软件包可能只安装到用户可写的位置。因此,当您第一次运行程序并检测到正确的位置时,复制字体可能会提示您以比setup.py更好的方式做东西,例如:通过密码提示提升权限以防万一需要时,请求一个不同的位置,如果你不能检测到它,提示你是否覆盖现有的系统文件等。

我曾经试图争论Python包应该能够放置在/etc的东西,但我意识到好处是小而不是为目标操作系统创建适当的本地软件包,例如Debian的Debian软件包或Windows的.exe安装程序。

底线是轮子和setuptools不是整个操作系统的包管理器,而仅仅是当地的一些site-packages/

我希望这个答案给你足够的背景,以避免data_files。最后一个很好的理由:让它跨越distutils,setuptools和wheel工作是一个不行。

+0

谢谢您的回复。我正在考虑将'setup.py'文件中的字体移动到'setup()'执行完后,并且在我尝试删除matplotlib的fontList缓存之前。相反,您建议在某人第一次运行我的程序时移动字体。我怎么会这样做,只有有人第一次'进口clearplot'?似乎每次有人输入clearplot时都需要检查。 – Stretch

+0

哦,我看你建议我创建一个本地包(.exe安装程序或debian包)。这似乎是很多工作,只是移动一个文件。 – Stretch

+0

在未安装软件包的情况下,在setup.py中使用软件包数据可能会出现问题。你还应该考虑上面列出的其他原因。创建一个本地安装程序应该是你和你的项目的前进方向......但我明白,这看起来像是一个非常大的努力。我的经验是,它回报:) – benjaoming

相关问题