2016-03-05 134 views
8

我使用pyinstaller構建我的燒瓶應用程序, 一切工作正常,除非我遇到Jinja2模板的問題。Pyinstaller Jinja2 TemplateNotFound

它給了我jinja2.exceptions.TemplateNotFound

我試圖把from app import template這是模板文件夾,但它沒有工作(我猜,因爲它們不包含任何py文件)。

我也試圖改變.spec文件以包括templates文件夾

added_files = [ 
     ('..\\CommerceApp\\app\\templates', 'templates'), 
     ('..\\CommerceApp\\app\\static', 'static') 
     ] 

a = Analysis(['..\\CommerceApp\\run.py'], 
      pathex=['D:\\PythonProjects\\CommerceAppExe'], 
      binaries=None, 
      datas=added_files, 
      hiddenimports=[], 
      hookspath=[], 
      runtime_hooks=[], 
      excludes=[], 
      win_no_prefer_redirects=False, 
      win_private_assemblies=False, 
      cipher=block_cipher) 

但是,如果我通過自己手動複製文件夾它也不能工作,同樣的結果。

有什麼辦法可以將模板與.exe捆綁在一起?


編輯

這是我spec文件

# -*- mode: python -*- 

block_cipher = None 

a = Analysis(['..\\CommerceApp_withPyInstaller\\run.py'], 
      pathex=['D:\\PythonProjects\\CommerceAppExe'], 
      binaries=None, 
      datas=[], 
      hiddenimports=[], 
      hookspath=[], 
      runtime_hooks=[], 
      excludes=[], 
      win_no_prefer_redirects=False, 
      win_private_assemblies=False, 
      cipher=block_cipher) 
pyz = PYZ(a.pure, a.zipped_data, 
      cipher=block_cipher) 
exe = EXE(pyz, 
      a.scripts, 
      exclude_binaries=True, 
      name='SupplyTracker', 
      debug=False, 
      strip=False, 
      upx=True, 
      console=True) 
coll = COLLECT(exe, 
       a.binaries, 
       a.zipfiles, 
       a.datas, 
       strip=False, 
       upx=True, 
       name='SupplyTracker') 

編輯2

接受的答案改變爲gmas80是導致它解決了這個問題。

編輯3

此外,我才意識到,我可以做一個新的文件夾我的包名稱和靜態模板csshtml等填充,這是要去工作(從類似的結果是什麼gmas80腳本)

+0

創建1文件夾凍結應用程序並檢查是否收集了所有的模板文件! – gmas80

回答

5

我不認爲這個問題是https://stackoverflow.com/a/35816876/2741329中描述的問題。我剛剛能夠用Jinja2來凍結一個應用程序。

在我的規格文件,我用這種方式來收集所有的模板:

from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT, BUNDLE, TOC 


def collect_pkg_data(package, include_py_files=False, subdir=None): 
    import os 
    from PyInstaller.utils.hooks import get_package_paths, remove_prefix, PY_IGNORE_EXTENSIONS 

    # Accept only strings as packages. 
    if type(package) is not str: 
     raise ValueError 

    pkg_base, pkg_dir = get_package_paths(package) 
    if subdir: 
     pkg_dir = os.path.join(pkg_dir, subdir) 
    # Walk through all file in the given package, looking for data files. 
    data_toc = TOC() 
    for dir_path, dir_names, files in os.walk(pkg_dir): 
     for f in files: 
      extension = os.path.splitext(f)[1] 
      if include_py_files or (extension not in PY_IGNORE_EXTENSIONS): 
       source_file = os.path.join(dir_path, f) 
       dest_folder = remove_prefix(dir_path, os.path.dirname(pkg_base) + os.sep) 
       dest_file = os.path.join(dest_folder, f) 
       data_toc.append((dest_file, source_file, 'DATA')) 

    return data_toc 

pkg_data = collect_pkg_data('<YOUR LIB HERE>') 

然後加入pkg_dataCOLLECT(1文件夾),或在EXE(1文件)的.spec。

在1文件夾解決方案中,您應該能夠在創建的子文件夾中找到所有模板。


編輯

這可能會實現(假設你有一個包(即你有一個__init__.py)以下建議:http://flask.pocoo.org/docs/0.10/patterns/packages/):

# -*- mode: python -*- 

# <<< START ADDED PART  
from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT, BUNDLE, TOC 


def collect_pkg_data(package, include_py_files=False, subdir=None): 
    import os 
    from PyInstaller.utils.hooks import get_package_paths, remove_prefix, PY_IGNORE_EXTENSIONS 

    # Accept only strings as packages. 
    if type(package) is not str: 
     raise ValueError 

    pkg_base, pkg_dir = get_package_paths(package) 
    if subdir: 
     pkg_dir = os.path.join(pkg_dir, subdir) 
    # Walk through all file in the given package, looking for data files. 
    data_toc = TOC() 
    for dir_path, dir_names, files in os.walk(pkg_dir): 
     for f in files: 
      extension = os.path.splitext(f)[1] 
      if include_py_files or (extension not in PY_IGNORE_EXTENSIONS): 
       source_file = os.path.join(dir_path, f) 
       dest_folder = remove_prefix(dir_path, os.path.dirname(pkg_base) + os.sep) 
       dest_file = os.path.join(dest_folder, f) 
       data_toc.append((dest_file, source_file, 'DATA')) 

    return data_toc 

pkg_data = collect_pkg_data('<yourapplication>') # <<< Put the name of your package here 
# <<< END ADDED PART  

block_cipher = None 

a = Analysis(['..\\CommerceApp_withPyInstaller\\run.py'], 
      pathex=['D:\\PythonProjects\\CommerceAppExe'], 
      binaries=None, 
      datas=[], 
      hiddenimports=[], 
      hookspath=[], 
      runtime_hooks=[], 
      excludes=[], 
      win_no_prefer_redirects=False, 
      win_private_assemblies=False, 
      cipher=block_cipher) 
pyz = PYZ(a.pure, a.zipped_data, 
      cipher=block_cipher) 
exe = EXE(pyz, 
      a.scripts, 
      exclude_binaries=True, 
      name='SupplyTracker', 
      debug=False, 
      strip=False, 
      upx=True, 
      console=True) 
coll = COLLECT(exe, 
       a.binaries, 
       a.zipfiles, 
       a.datas, 
       pkg_data, # <<< Add here the collected files 
       strip=False, 
       upx=True, 
       name='SupplyTracker') 
+0

嘿,對不起,如果我不知道,你如何把'pkg_data'屬性放入'specl'中的'spec' '文件?我試着把腳本的'pathname'(../path/to/pkg_data.py)放進去,但它不起作用。我應該在我的主腳本中輸入腳本嗎?或者把它放在'Analysis'屬性的某個地方?謝謝 – andiwin

+0

@ kingathur61:你爲什麼不把你的整個spec文件放在問題體內?所以我可以編輯它,因爲我相信這可能會奏效。 – gmas80

+0

我在我的編輯中添加了spec文件 – andiwin

2

Jinja2程序包使用pkg_resources API,PyInstaller不支持該API。 pkg_resources模塊通過setuptools包提供。

FAQpyinstaller

通過pkg_resources目前不支持PyInstaller。這意味着 使用API​​的應用程序使用pkg_resources API可能無法正常工作。其中 工作的唯一情況是在.egg文件上使用它(請參閱上文)。有關 的詳細信息,請參閱問題#183。

+0

啊,我明白了,所以在pyinstaller更新之前,我無能爲力? – andiwin

+0

@Forge和@ kingathur61:''jinja2.exceptions.TemplateNotFound''與「pkg_resources」無關。否則,它會有所不同:https://github.com/pyinstaller/pyinstaller/issues/1898 – gmas80