使用pyInstaller打包的一点经验

来源:互联网 发布:英语网络热词怎么来的 编辑:程序博客网 时间:2024/05/18 00:16

1 Popen

class subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

在脚本状态下stdout=None,  stderr=None时运行不会有任何问题,但经过pyInstall打包成exe后,运行时会出现 ”[Error 6] The handle is invalid” 异常,解决方法如下:

脚本原始调用方法

Import subprocess

p = subprocess.Popen("myapp.exe", stdin=subprocess.PIPE, stdout=None, stderr=None)

p.stdin.write('xxx')

 

适配pyInstaller的写法

Import subprocess

p = subprocess.Popen("x.exe", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

p.stdin.write('xxx')

p.stdout.close()

p.stderr.close()

2 Multiprocessing

代码中直接使用标准库中的multiprocessing.Processmultiprocessing.Pool,在打包成可执行程序后会创建进程失败。

对于pyinstallerone-directory模式,只要再程序的最开始调用multiprocessing. freeze_support()就可以了,但对于one-file模式,还需要使用下面修改后的ProcessPool

import multiprocessing.forking

import multiprocessing.pool

import os

import sys

class _Popen(multiprocessing.forking.Popen):

   def __init__(self, *args, **kw):

       if hasattr(sys, 'frozen'):

           # We have to set original _MEIPASS2 value from sys._MEIPASS

           # to get --onefile mode working.

           # Last character is stripped in C-loader. We have to add

           # '/' or '\\' at the end.

           os.putenv('_MEIPASS2', sys._MEIPASS + os.sep)

       try:

           super(_Popen, self).__init__(*args, **kw)

       finally:

           if hasattr(sys, 'frozen'):

               # On some platforms (e.g. AIX) 'os.unsetenv()' is not

               # available. In those cases we cannot delete the variable

               # but only set it to the empty string. The bootloader

               # can handle this case.

               if hasattr(os, 'unsetenv'):

                   os.unsetenv('_MEIPASS2')

               else:

                   os.putenv('_MEIPASS2', '')

 

classProcess(multiprocessing.Process):

   _Popen = _Popen

   

classPool(multiprocessing.pool):

   Process = Process

3 模块引用

脚本运行状态下,当需要使用全路径引用py文件时(如当前模块路径的父目录中的.py文件),可以通过添加路径的方法减少引用层数。假设plugins处于代码的根目录下,如果想引用plugins\Demo1\Demo1MainFrame.py,可以用下述方法:

Import plugin.Demo1. Demo1MainFrame

也可以先在程序最开始执行:

sys.path.append("./Plugins")

然后再使用:

Import Demo1. Demo1MainFrame

 

但遗憾的是,这种方法在pyInstaller打包后的程序中不能使用,会出现模块导入错误。

 

4 其它

  • 打包过程中若遇到临时文件访问权限的问题,可临时禁用杀毒和防火墙功能后再尝试;
  • pyInstall仅支持ascii编码方式,打包后可执行文件数径中不能有中文。

 

2 0
原创粉丝点击