py2exe-生成单个可执行文件

问题:py2exe-生成单个可执行文件

我以为我听说py2exe可以做到这一点,但我从来没有想过。有人成功做到了吗?我可以看到您的setup.py文件以及使用的哪些命令行选项吗?

基本上,我正在考虑给它提供一个可执行文件,该文件可执行将自身解压缩到/ temp并运行的操作。

I thought I heard that py2exe was able to do this, but I never figured it out. Has anyone successfully done this? Can I see your setup.py file, and what command line options you used?

Basically I’m thinking of it giving me a single executable file that does something like unzips itself to maybe /temp and runs.


回答 0

PyInstaller将创建一个没有依赖关系的.exe文件;使用该--onefile选项。它通过将所有需要的共享库打包到可执行文件中,并在运行之前解压缩它们来完成此操作,正如您所描述的那样(编辑:py2exe也具有此功能,请参见minty的答案

我使用的是svn的PyInstaller版本,因为最新版本(1.3)有点过时了。对于依赖于PyQt,PyQwt,numpy,scipy等应用程序的应用程序来说,它的运行情况非常好。

PyInstaller will create a single .exe file with no dependencies; use the --onefile option. It does this by packing all the needed shared libs into the executable, and unpacking them before it runs, just as you describe (EDIT: py2exe also has this feature, see minty’s answer)

I use the version of PyInstaller from svn, since the latest release (1.3) is somewhat outdated. It’s been working really well for an app which depends on PyQt, PyQwt, numpy, scipy and a few more.


回答 1

使用py2exe进行此操作的方法是在setup.py文件中使用bundle_files选项。对于单个文件,您将需要设置bundle_files为1,compressed为True,并将zipfile选项设置为None。这样,它会创建一个压缩文件以便于分发。

这是直接从py2exe网站引用的bundle_file选项的更完整说明*

使用“ bundle_files”和“ zipfile”

创建单文件可执行文件的一种更简单(更好)的方法是将bundle_files设置为1或2,并将zipfile设置为None。这种方法不需要将文件提取到一个临时位置,从而可以更快地启动程序。

bundle_files的有效值为:

  • 3(默认)不捆绑
  • 2捆绑除Python解释器以外的所有内容
  • 1捆绑一切,包括Python解释器

如果zipfile设置为None,则文件将捆绑在可执行文件中,而不是在library.zip中。

这是一个示例setup.py:

from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

setup(
    options = {'py2exe': {'bundle_files': 1, 'compressed': True}},
    windows = [{'script': "single.py"}],
    zipfile = None,
)

The way to do this using py2exe is to use the bundle_files option in your setup.py file. For a single file you will want to set bundle_files to 1, compressed to True, and set the zipfile option to None. That way it creates one compressed file for easy distribution.

Here is a more complete description of the bundle_file option quoted directly from the py2exe site*

Using “bundle_files” and “zipfile”

An easier (and better) way to create single-file executables is to set bundle_files to 1 or 2, and to set zipfile to None. This approach does not require extracting files to a temporary location, which provides much faster program startup.

Valid values for bundle_files are:

  • 3 (default) don’t bundle
  • 2 bundle everything but the Python interpreter
  • 1 bundle everything, including the Python interpreter

If zipfile is set to None, the files will be bundle within the executable instead of library.zip.

Here is a sample setup.py:

from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

setup(
    options = {'py2exe': {'bundle_files': 1, 'compressed': True}},
    windows = [{'script': "single.py"}],
    zipfile = None,
)

回答 2

就像其他海报提到的那样,py2exe将生成一个可执行文件和一些要加载的库。您还可以将一些数据添加到程序中。

下一步是使用安装程序,将所有这些程序打包到一个易于使用的可安装/不可安装程序中。

我使用InnoSetup(http://www.jrsoftware.org/isinfo.php)已经有好几年了,并且用于商业程序,所以我衷心推荐它。

As the other poster mention, py2exe, will generate an executable + some libraries to load. You can also have some data to add to your program.

Next step is to use an installer, to package all this into one easy-to-use installable/unistallable program.

I have used InnoSetup ( http://www.jrsoftware.org/isinfo.php ) with delight for several years and for commercial programs, so I heartily recommend it.


回答 3

我已经能够将所有资源嵌入到exe中来创建一个exe文件。我在Windows上构建。这样就可以解释我正在使用的os.system调用。

首先,我尝试将所有图像转换为位垫,然后将所有数据文件转换为文本字符串。但这导致最终exe变得非常大。

谷歌搜索一周后,我想出了如何更改py2exe脚本以满足我的需求。

这是我提交的有关sourceforge的补丁程序链接,请发表评论,以便我们将其包含在下一个发行版中。

http://sourceforge.net/tracker/index.php?func=detail&aid=3334760&group_id=15583&atid=315583

这使所做的所有更改无效,我只是在设置行中添加了一个新选项。这是我的setup.py。

我将尽我所能评论。请知道我的setup.py很复杂,因为我要按文件名访问图像。所以我必须存储一个列表来跟踪它们。

这是我试图制作的“想要”屏幕保护程序。

我使用exec在运行时生成设置,这样更容易剪切和粘贴。

exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
      'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
      options={'py2exe': py2exe_options},\
      zipfile = None )" % (bitmap_string[:-1])

分解

脚本= PY脚本,我想转向一个EXE

icon_resources = exe的图标

file_resources =我要嵌入exe的文件

other_resources =要嵌入到exe中的字符串,在这种情况下为文件列表。

options = py2exe用于将所有内容创建到一个exe文件中的选项

bitmap_strings =要包含的文件列表

请注意,只有按照上述链接中所述编辑py2exe.py文件后,file_resources才是有效选项。

第一次尝试在此站点上发布代码,如果我弄错了,请不要解雇我。

from distutils.core import setup
import py2exe #@UnusedImport
import os

#delete the old build drive
os.system("rmdir /s /q dist")

#setup my option for single file output
py2exe_options = dict( ascii=True,  # Exclude encodings
                       excludes=['_ssl',  # Exclude _ssl
                                 'pyreadline', 'difflib', 'doctest', 'locale',
                                 'optparse', 'pickle', 'calendar', 'pbd', 'unittest', 'inspect'],  # Exclude standard library
                       dll_excludes=['msvcr71.dll', 'w9xpopen.exe',
                                     'API-MS-Win-Core-LocalRegistry-L1-1-0.dll',
                                     'API-MS-Win-Core-ProcessThreads-L1-1-0.dll',
                                     'API-MS-Win-Security-Base-L1-1-0.dll',
                                     'KERNELBASE.dll',
                                     'POWRPROF.dll',
                                     ],
                       #compressed=None,  # Compress library.zip
                       bundle_files = 1,
                       optimize = 2                        
                       )

#storage for the images
bitmap_string = '' 
resource_string = ''
index = 0

print "compile image list"                          

for image_name in os.listdir('images/'):
    if image_name.endswith('.jpg'):
        bitmap_string += "( " + str(index+1) + "," + "'" + 'images/' + image_name + "'),"
        resource_string += image_name + " "
        index += 1

print "Starting build\n"

exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
      'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
      options={'py2exe': py2exe_options},\
      zipfile = None )" % (bitmap_string[:-1])

print "Removing Trash"
os.system("rmdir /s /q build")
os.system("del /q *.pyc")
print "Build Complete"

好的,这就是setup.py了,现在魔术需要访问图像。我在开发此应用程序时没有考虑到py2exe,后来又添加了它。因此您会看到两种情况的访问权限。如果找不到图像文件夹,它将尝试从exe资源中提取图像。代码将对此进行解释。这是我的Sprite类的一部分,它使用Directx。但是您可以使用所需的任何api或仅访问原始数据。没关系

def init(self):
    frame = self.env.frame
    use_resource_builtin = True
    if os.path.isdir(SPRITES_FOLDER):
        use_resource_builtin = False
    else:
        image_list = LoadResource(0, u'INDEX', 1).split(' ')

    for (model, file) in SPRITES.items():
        texture = POINTER(IDirect3DTexture9)()
        if use_resource_builtin: 
            data = LoadResource(0, win32con.RT_RCDATA, image_list.index(file)+1) #windll.kernel32.FindResourceW(hmod,typersc,idrsc)               
            d3dxdll.D3DXCreateTextureFromFileInMemory(frame.device,   #Pointer to an IDirect3DDevice9 interface
                                              data,                #Pointer to the file in memory
                                              len(data),           #Size of the file in memory
                                              byref(texture))      #ppTexture
        else:
            d3dxdll.D3DXCreateTextureFromFileA(frame.device, #@UndefinedVariable
                                               SPRITES_FOLDER + file,
                                               byref(texture))            
        self.model_sprites[model] = texture
    #else:
    #    raise Exception("'sprites' folder is not present!")

任何问题都可以随意提出。

I’ve been able to create a single exe file with all resources embeded into the exe. I’m building on windows. so that will explain some of the os.system calls i’m using.

First I tried converting all my images into bitmats and then all my data files into text strings. but this caused the final exe to be very very large.

After googleing for a week i figured out how to alter py2exe script to meet my needs.

here is the patch link on sourceforge i submitted, please post comments so we can get it included in the next distribution.

http://sourceforge.net/tracker/index.php?func=detail&aid=3334760&group_id=15583&atid=315583

this explanes all the changes made, i’ve simply added a new option to the setup line. here is my setup.py.

i’ll try to comment it as best I can. Please know that my setup.py is complex do to the fact that i’m access the images by filename. so I must store a list to keep track of them.

this is from a want-to-b screen saver I was trying to make.

I use exec to generate my setup at run time, its easyer to cut and paste like that.

exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
      'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
      options={'py2exe': py2exe_options},\
      zipfile = None )" % (bitmap_string[:-1])

breakdown

script = py script i want to turn to an exe

icon_resources = the icon for the exe

file_resources = files I want to embed into the exe

other_resources = a string to embed into the exe, in this case a file list.

options = py2exe options for creating everything into one exe file

bitmap_strings = a list of files to include

Please note that file_resources is not a valid option untill you edit your py2exe.py file as described in the link above.

first time i’ve tried to post code on this site, if I get it wrong don’t flame me.

from distutils.core import setup
import py2exe #@UnusedImport
import os

#delete the old build drive
os.system("rmdir /s /q dist")

#setup my option for single file output
py2exe_options = dict( ascii=True,  # Exclude encodings
                       excludes=['_ssl',  # Exclude _ssl
                                 'pyreadline', 'difflib', 'doctest', 'locale',
                                 'optparse', 'pickle', 'calendar', 'pbd', 'unittest', 'inspect'],  # Exclude standard library
                       dll_excludes=['msvcr71.dll', 'w9xpopen.exe',
                                     'API-MS-Win-Core-LocalRegistry-L1-1-0.dll',
                                     'API-MS-Win-Core-ProcessThreads-L1-1-0.dll',
                                     'API-MS-Win-Security-Base-L1-1-0.dll',
                                     'KERNELBASE.dll',
                                     'POWRPROF.dll',
                                     ],
                       #compressed=None,  # Compress library.zip
                       bundle_files = 1,
                       optimize = 2                        
                       )

#storage for the images
bitmap_string = '' 
resource_string = ''
index = 0

print "compile image list"                          

for image_name in os.listdir('images/'):
    if image_name.endswith('.jpg'):
        bitmap_string += "( " + str(index+1) + "," + "'" + 'images/' + image_name + "'),"
        resource_string += image_name + " "
        index += 1

print "Starting build\n"

exec "setup(console=[{'script': 'launcher.py', 'icon_resources': [(0, 'ICON.ico')],\
      'file_resources': [%s], 'other_resources': [(u'INDEX', 1, resource_string[:-1])]}],\
      options={'py2exe': py2exe_options},\
      zipfile = None )" % (bitmap_string[:-1])

print "Removing Trash"
os.system("rmdir /s /q build")
os.system("del /q *.pyc")
print "Build Complete"

ok, thats it for the setup.py now the magic needed access the images. I developed this app without py2exe in mind then added it later. so you’ll see access for both situations. if the image folder can’t be found it tries to pull the images from the exe resources. the code will explain it. this is part of my sprite class and it uses a directx. but you can use any api you want or just access the raw data. doesn’t matter.

def init(self):
    frame = self.env.frame
    use_resource_builtin = True
    if os.path.isdir(SPRITES_FOLDER):
        use_resource_builtin = False
    else:
        image_list = LoadResource(0, u'INDEX', 1).split(' ')

    for (model, file) in SPRITES.items():
        texture = POINTER(IDirect3DTexture9)()
        if use_resource_builtin: 
            data = LoadResource(0, win32con.RT_RCDATA, image_list.index(file)+1) #windll.kernel32.FindResourceW(hmod,typersc,idrsc)               
            d3dxdll.D3DXCreateTextureFromFileInMemory(frame.device,   #Pointer to an IDirect3DDevice9 interface
                                              data,                #Pointer to the file in memory
                                              len(data),           #Size of the file in memory
                                              byref(texture))      #ppTexture
        else:
            d3dxdll.D3DXCreateTextureFromFileA(frame.device, #@UndefinedVariable
                                               SPRITES_FOLDER + file,
                                               byref(texture))            
        self.model_sprites[model] = texture
    #else:
    #    raise Exception("'sprites' folder is not present!")

Any questions fell free to ask.


回答 4

如前所述,您应该创建一个安装程序。即使也可以通过将bundle_files选项设置为1并将zipfile关键字参数设置为None来让py2exe将所有内容捆绑到一个可执行文件中,但我不建议PyGTK应用程序使用此方法。

这是因为GTK +试图从其加载目录中加载其数据文件(本地,主题等)。因此,您必须确保可执行文件的目录还包含GTK +使用的库以及GTK +安装中的目录lib,share等。否则,您将在未在全系统范围内安装GTK +的计算机上运行应用程序时遇到问题。

有关更多详细信息,请阅读我的PyGTK应用程序py2exe指南。它还说明了如何捆绑除GTK +之外的所有内容。

You should create an installer, as mentioned before. Even though it is also possible to let py2exe bundle everything into a single executable, by setting bundle_files option to 1 and the zipfile keyword argument to None, I don’t recommend this for PyGTK applications.

That’s because of GTK+ tries to load its data files (locals, themes, etc.) from the directory it was loaded from. So you have to make sure that the directory of your executable contains also the libraries used by GTK+ and the directories lib, share and etc from your installation of GTK+. Otherwise you will get problems running your application on a machine where GTK+ is not installed system-wide.

For more details read my guide to py2exe for PyGTK applications. It also explains how to bundle everything, but GTK+.


回答 5

我被告知bbfreeze将创建一个文件.EXE,并且比py2exe更新。

I’m told bbfreeze will create a single file .EXE, and is newer than py2exe.


回答 6

尝试 c_x Frozen 它可以创建一个很好的独立版本

try c_x freeze it can create a good standalone


回答 7

我最近使用py2exe创建了一个用于后期审阅的可执行文件,用于将审阅发送到ReviewBoard。

这是我使用的setup.py

from distutils.core import setup
import py2exe

setup(console=['post-review'])

它创建了一个目录,其中包含exe文件和所需的库。我认为无法使用py2exe来获取单个.exe文件。如果需要,首先需要使用py2exe,然后使用某种形式的安装程序来制作最终的可执行文件。

需要注意的一件事是,您在应用程序中使用的任何egg文件都需要解压缩,否则py2exe不能包含它们。py2exe文档中对此进行了介绍。

I recently used py2exe to create an executable for post-review for sending reviews to ReviewBoard.

This was the setup.py I used

from distutils.core import setup
import py2exe

setup(console=['post-review'])

It created a directory containing the exe file and the libraries needed. I don’t think it is possible to use py2exe to get just a single .exe file. If you need that you will need to first use py2exe and then use some form of installer to make the final executable.

One thing to take care of is that any egg files you use in your application need to be unzipped, otherwise py2exe can’t include them. This is covered in the py2exe docs.


回答 8

不,就您以后只有一个文件的意义而言,它没有给您单个可执行文件-但您有一个目录,其中包含运行程序所需的所有文件,包括exe文件。

我今天才写了这个setup.py。您只需要调用python setup.py py2exe

No, it’s doesn’t give you a single executable in the sense that you only have one file afterwards – but you have a directory which contains everything you need for running your program, including an exe file.

I just wrote this setup.py today. You only need to invoke python setup.py py2exe.