2016-03-12 34 views
7

在kivy论坛没有得到响应,所以试着在这里。Kivy:编译成单个可执行文件

当我将教程pong代码编译为一个文件可执行文件时,我仍然必须将pong.kv文件包含在相同的文件夹中才能运行。 否则,启动exe文件时,我得到了以下错误:

 

    GL: EXT_framebuffer_object is supported 
    [INFO    ] [GL   ] OpenGL version 
    [INFO    ] [GL   ] OpenGL vendor 
    [INFO    ] [GL   ] OpenGL renderer 
    [INFO    ] [GL   ] OpenGL parsed version: 2, 1 
    [INFO    ] [GL   ] Shading version 
    [INFO    ] [GL   ] Texture max size 
    [INFO    ] [GL   ] Texture max units 
    [INFO    ] [Window  ] auto add sdl2 input provider 
    [INFO    ] [Window  ] virtual keyboard not allowed, 
    single mode, not docked 
    Traceback (most recent call last): 
     File "", line 81, in 
     File "c:\python34\lib\site-packages\kivy\app.py", line 802, in 
    run 
     root = self.build() 
     File "", line 75, in build 
     File "", line 20, in serveBall 
    AttributeError: 'NoneType' object has no attribute 'center' 
    main returned -1 

我怎样才能得到它作为一个可执行文件运行。这是我的pong.spec文件:



    # -*- mode: python -*- 

    from kivy.deps import sdl2, glew 

    block_cipher = None 


    a = Analysis(['Code\main.py'], 
       pathex=['E:\\Development\\Pong'], 
       binaries=None, 
       datas=None, 
       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) 

    a.datas += [('Code\pong.kv', 'E:\\Development\\Pong\Code\pong.kv', 'DATA')] 

    exe = EXE(pyz,Tree('Code'), 
       a.scripts, 
       a.binaries, 
       a.zipfiles, 
       a.datas, 
       *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)], 
       name='pong', 
       debug=False, 
       strip=False, 
       upx=True, 
       console=True , icon='pong.ico') 

请注意,我试图将pong.kv包含在数据列表中,但没有帮助。

感谢, -Raj

+0

我听说这是可能的,也有一些人做到了,但即使有这些,我也没有运气:[1](http://irwinkwan.com/2013/04/29/python-executables-pyinstaller-and - 48小时游戏设计组合/),[2](http://stackoverflow.com/questions/7674790/bundling-data-files-with-pyinstaller-onefile)。虽然看起来像是一个矫枉过正(因为.exe大小),但应该记录正在运行的'onefile'选项。 – KeyWeeUsr

+1

对于其他数据文件,您建议的方法最终会为我工作。但是,为了加载默认的.kv文件,我最终调用了kivy.resource_add_path(resourcePath()),其中resourcePath在__main__部分返回了sys._MEIPASS(或者未编译时的本地开发路径)。这似乎工作;也许会为你呢? – Raj

+0

我希望它会。您可以用简单的例子将[onefile]打包步骤附加到[docs](https://kivy.org/docs/guide/packaging-windows.html)/ [wiki](https://github.com/kivy/) kivy/wiki)如果该exe可以处理所有资源和'.kv'?我认为能够将它放在那里供将来参考是很好的。 – KeyWeeUsr

回答

4

基于KeyWeeUsr提供的链接(Bundling data files with PyInstallerUsing PyInstaller to make EXEs from Python scripts),并将其与Kivy的资源路径方法相结合,这里有一个可行的解决方案。我觉得这有点粗糙,因为它使用SYS._MEIPASS(我更喜欢公共API),并且需要在Python代码中添加代码片段。但是,该解决方案在Windows和Mac上都可以共享。

假设我有以下代码层次:

 
MyCode/ 
    MyApp.py (This is the main program) 
    myapp.kv (This is the associated kv file) 

    MyData/  (This is where data is located that the app uses) 
     myapp.icns (e.g. icon file for mac) 
     myapp.ico (e.g. icon file for windows) 

Build/ 
    mac/ 
     myapp.spec (spec file to build on mac platform) 
    pc/ 
     myapp.spec (spec file to build on windows platform) 

MyHiddenImports/ (Folder containing python files for hidden imports) 

我的情况下,你的代码还包含附加Python代码在运行时的sys.path另一个文件夹添加一个文件夹MyHiddenImports的例子。

在MyApp.py添加以下内容:

def resourcePath(): 
    '''Returns path containing content - either locally or in pyinstaller tmp file''' 
    if hasattr(sys, '_MEIPASS'): 
     return os.path.join(sys._MEIPASS) 

    return os.path.join(os.path.abspath(".")) 

if __name__ == '__main__': 
    kivy.resources.resource_add_path(resourcePath()) # add this line 
    my_app = MyApp() 

的resources_add_path()告诉Kivy到哪里寻找数据/ .kv文件。例如,在Mac上,当运行pyinstaller应用程序时,它指向/ private/var/folders/80/y766cxq10fb_794019j7qgnh0000gn/T/_MEI25602,并在Windows中指向c:\ users \ raj \ AppData \ Local \ Temp_MEI64zTut这些文件夹在退出应用程序后被删除,并在再次启动时创建另一个名称)。

我创建用下面的命令初始MAC模板spec文件:

pyinstaller --onefile -y --clean --windowed --name MYAPP --icon = .. /。 ./Code/Data/myapp.icns --exclude模块_tkinter --exclude模块Tkinter的--exclude模块点化--exclude模块扭曲../../Code/MyApp.py

以下是修改后的Mac OS Spec文件:

# -*- mode: python -*- 

block_cipher = None 


a = Analysis(['../../Code/MyApp.py'], 
      pathex=['/Users/raj/Development/Build/mac', 
      '../../MyHiddenImports'],  
      binaries=None, 
      datas=None, 
      hiddenimports=['MyHiddenImports'],  
      hookspath=[], 
      runtime_hooks=[], 
      excludes=['_tkinter', 'Tkinter', 'enchant', 'twisted'], 
      win_no_prefer_redirects=False, 
      win_private_assemblies=False, 
      cipher=block_cipher) 

pyz = PYZ(a.pure, a.zipped_data, 
      cipher=block_cipher) 

a.datas += [('myapp.kv', '../../MyCode/my.kv', 'DATA')] 

exe = EXE(pyz, Tree('../../Code/Data', 'Data'), 
      a.scripts, 
      a.binaries, 
      a.zipfiles, 
      a.datas, 
      name='myapp', 
      debug=False, 
      strip=False, 
      upx=True, 
      console=False , icon='../../Code/Data/myapp.icns') 

app = BUNDLE(exe, 
      name='myapp.app', 
      icon='../../Code/Data/myapp.icns', 
      bundle_identifier=None) 

注意事项:我将隐藏的导入路径添加到了pathex,并在hiddenimports中引用了该包。我将myapp.kv文件附加到数据库中,以便将其复制到应用程序中。在EXE中,我添加了数据树。我包含前缀参数,因为我想将Data文件夹复制到应用程序中(而不是让孩子坐在根级别)。

要编译的代码来创建应用程序,并把它变成一个dmg文件我有一个化妆的myapp脚本执行以下操作:

 
pyinstaller -y --clean --windowed myapp.spec 
pushd dist 
hdiutil create ./myapp.dmg -srcfolder myapp.app -ov 
popd 
cp ./dist/myapp.dmg . 

同样,这里的窗口规范文件:

# -*- mode: python -*- 

from kivy.deps import sdl2, glew 

block_cipher = None 


a = Analysis(['..\\..\\Code\\Cobbler.py'], 
      pathex=['E:\\Development\\MyApp\\Build\\pc', 
      '..\\..\\MyHiddenImports'], 
      binaries=None, 
      datas=None, 
      hiddenimports=['MyHiddenImports'], 
      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) 

a.datas += [('myapp.kv', '../../Code/myapp.kv', 'DATA')] 

exe = EXE(pyz, Tree('..\\..\\Code\\Data','Data'), 
      a.scripts, 
      a.binaries, 
      a.zipfiles, 
      a.datas, 
      *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)], 
      name='myapp', 
      debug=False, 
      strip=False, 
      upx=True, 
      console=False, icon='..\\..\\Code\\Data\\myapp.ico') 

,并编制了Windows应用程序:

蟒蛇-m PyInstaller myapp.spec

+0

这很好,直到我运行最后的'.exe'。包含来自main.py文件夹的文件,代码有效,但唯一没有的是sdl2或更好的说'bin'文件夹。当我在Temp中检查MEI文件夹时,除了'SDL ...'之外,没有其他东西。没有''LICENSE ...',没有'lib ...'sdl2 bin文件夹,所以我得到[this](https://github.com/kivy/kivy/issues/3957)错误。 我的sdl2安装正确,我尝试了pyinstaller(works)中的一个文件夹选项,所以从'sharefile'到'share \ sdl2 \ bin'文件夹中获取'lib ...'有一定的错误 – KeyWeeUsr

+0

我不能在我的应用程序运行时使用sdl2中的任何内容。我查看了临时文件夹,并没有看到sdl LICENSE等文件。只需在根文件夹中使用基本的sdl dll。是否有一段代码可以尝试编译以查看我得到的内容? – Raj

+0

那么,我试着用touchtracer演示和你的指令和规格,所以... – KeyWeeUsr

0

如果你不关心的码长,怎么样使用Builder.load_string一个.py文件中加载千伏数据?这样整个代码就保存在你的python脚本中,这可能有助于将它编译为.exe。

+0

这可能是一种方式,但不是一个好的。想象一下,他会有图片和其他东西,不仅是'.kv'。 – KeyWeeUsr

+0

正确,我有图标文件和一些额外的数据文件,现在坐在一边.exe。在Mac上,我可以在后处理步骤中将文件移动到不太理想的.app文件夹中,并想知道我是否会在将来签署问题。 – Raj

+0

那么使用gettext的多语言呢?将难以获得本地化的字符串。 –

相关问题