标签:support effort ros loader ++ free options eth python 2
For years, NVDA has used Py2exe to package Python code into something that is executable on a system that doesn‘t have Python installed. For Python 2.7, we have been at Py2exe 0.6.9 (introduced in 2008) for a long time. For Python 3, a new version has been introduced in 2014 which looks like a rewrite. The last official release (0.9.2.2) was introduced in 2014.
Starting with Python 3.6 (end 2016) however, Python contains a backwards incompatible change of the byte code format that is not supported by the official py2exe.
Note that many parts of the build process of NVDA are handled by SCons. This includes:
In summary, Scons deals with everything that is required to run NVDA from source, Py2exe is not involved in that process. Py2exe gets called as soon as a distribution of NVDA is created. The portable distribution that Py2exe creates is then packed into a launcher using NSiS.
Before deciding on what packaging tool to use, this section lists the requirements for a packaging tool, based on the work that is now performed by Py2exe.
Byte compile every source file into a *.pyc or *.pyo file. Note that for Python 3, only the *pyc files remain.
Byte compile every Python dependency (comtypes, pyserial, etc.) required to run NVDA.
Collect Python extension modules (*.pyd files)
Bundle the several byte compiled files into a library.zip file in the main folder of the distribution.
Exclude several unneeded modules
Create executables from certain source files:
source | destination(s) | description |
---|---|---|
nvda.pyw | nvda_noUIAccess.exe, nvda_uiAccess.exe | Main executables (see below) |
nvda_eoaProxy.pyw | nvda_eoaProxy.exe | Used to integrate in Windows 7 EOA center |
nvda_slave.pyw | nvda_slave.exe | Used for add-on installation from shell, elevated rights during installation, etc. |
Bundle a manifest with the executables. Theoretically, this can also be done using SCons, though in contrast to what I thought earlier, there is no code within the current scons structure of NVDA that can be reused for this.
Make sure that the UIAccess flag is added to the manifest of nvda_uiAccess.exe and nvda_eoaProxy.exe. Strictly spoken, this is code that has been added to our subclass of build_exe.py2exe in order to inject the UIAccess flag into the manifest created by py2exe. However, droppign py2exe in favour of another tool might force us to completely rewrite this logic.
Embed the NVDA logo into the executables as icon.
Set several version info flags in the version info resource of the executables.
Collect several system dll‘s not available on every system. This includes visual C++ redistributables.
Collect data files created using SCons, such as several libraries, language files, documentation, etc.
According to research and ideas from others, there are four packaging/freezing options that can be used with Python 3. The following sections provide short descriptions along with pros and cons.
See https://github.com/albertosottile/py2exe
Thankfully, @albertosottile contacted us in #8375 (comment), commenting that he picked up Py2exe where it has been abandoned in 2014. This resulted into a release of Py2exe 0.93.0. This version is said to work with Python 3.6 and 3.7.
It is planned to achive full compatibility with the setup-scripts for Python 2; however this is probably not yet the case.
Feature | supported |
---|---|
Create multiple executables | Yes |
Bundle manifest | Yes, but differently than before, might require pr to upstream |
UIAccess | No explicit support, see manifest |
Embed logo | Yes |
Set version info | Yes |
Collect system dll‘s | Yes |
Collect external Python dependencies and *.pyd files | Yes |
Collect data files | Yes |
Library file | Yes |
PyInstaller is an alternative tool to build executables. It also supports byte code encryption, though that seems not very useful in the case of NVDA.
Building multiple executables at once seems to be broken
It does not integrate very well with distutils. It looks like the PyInstaller documentation suggests using a batch file to write down command line commands. Alternatively, you can use a spec file. Writing a setup.py for your package seems unsupported. Having said that, we‘re now calling a python interpretter from scons to execute the setup script, so basically, we‘re using a command line call already. This is therefore no show stopper, just a change of approach.
More importantly, I‘ve seen ridiculous tracebacks with one of my test applications referring to pyinstaller:
Traceback (most recent call last):
File "main.py", line 1, in <module>
File "c:\python36\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
exec(bytecode, module.__dict__)
File "core.py", line 5, in <module>
File "c:\python36\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 631, in exec_module
exec(bytecode, module.__dict__)
It looks like every import is somehow redirected to pyInstaller. I‘m pretty sure this will cause issues with our use of comtypes com interface modules, globalPlugins, etc. which rely on appending paths to the module path variable. Showing raw paths to the python directory also looks a bit cheap, but I recall that with py2exe, we also had to work around this.
Here is the official features page from PyInstaller
Feature | supported |
---|---|
Create multiple executables | No, broken in v3.0, see pyinstaller/pyinstaller#1527 |
Bundle manifest | Yes |
UIAccess | Yes |
Embed logo | Yes |
Set version info | Yes |
Collect system dll‘s | Yes |
Collect external Python dependencies and *.pyd files | Yes |
Collect data files | Yes |
Library file | No, seems to require a custom implementation using scripting according to features section, but no information found in documentation so far |
This is an alternative that integrates well with distutils. Note that it is far from compatible with py2exe, so setup.py would still require an overhaul. Running cx_Freeze also results into a package structure that is very similar to the one py2exe creates, including a librar .zip file in the lib sub directory. The default settings do not create a zip file, but that can be customized easily.
cx_Freeze is hosted on GitHub. We can include it as a separate submodule. Though it requires some c code to be compiled, that shouldn‘t be that much of a problem and takes less than 20 seconds, so that doesn‘t justify an inclusion in misc deps in my opinion.
No official build supporting Python 3.7, we‘d have to build from source.
There is no built-in support for manifests and setting the UI Access privilege level. We will probably have to implement this manually, either by expanding setup.py or by building the base executables ourselves.
By default, cx_freeze assumes that all python stuff is in a lib sub directory (i.e. in lib/library.zip) rather than in the root of the folder where the executables live. This is not easily customisable and seems to be hard-coded behaviour. We‘re using the lib folder for our x86 libraries, storing the python library in there might be a bit ugly.
When there is a startup error, cx_Freeze shows an error message box including the name of cx_Freeze itself. This might be confusing for users.
The last commit for the project dates from september 2018. There are 260 open issues, including two from myself:
Both issues haven‘t gotten any attention.
Feature | supported |
---|---|
Create multiple executables | Yes |
Bundle manifest | No, should probably be embedded in base executables |
UIAccess | No |
Embed logo | Yes |
Set version info | Yes |
Collect system dll‘s | Yes |
Collect external Python dependencies and *.pyd files | Yes |
Collect data files | Yes |
Library file | Yes |
Suggestion by @ctoth in #8375 (comment)
Nuitka chooses a completely different approach. Instead of compiling the Python code to byte code and bundling a loader with it, it converts all code to c and then compiles it using VC++ and links it against the Python library. It also claims to be faster than CPython.
Feature | supported |
---|---|
Create multiple executables | Yes |
Bundle manifest | No |
UIAccess | No |
Embed logo | Yes |
Set version info | No |
Collect system dll‘s | No |
Collect external Python dependencies and *.pyd files | Unsure |
Collect data files | No |
Library file | No |
Based on the above outline, I propose the following order of investigation of our options:
Note that option 1, 2 and 3 could be worked on in parallel. I‘m tempted to consider Nuitka being out of scope for now.
标签:support effort ros loader ++ free options eth python 2
原文地址:https://www.cnblogs.com/xpvincent/p/11223829.html