linux、渗透测试、网络安全、CTF、windows

使用pyinstaller打包的坑

洛基的城堡:

项目中用到pyinstaller将python打成.exe可执行文件:


结果发现如下问题:


由于需要获取命令执行的状态值及返回信息,因此放弃了os.system,os.popen等,commands.getstatusoutput在windows平台也不能使用,因此选择subprocess模块。 os.system还有个坑,当cmd有多个引号时,会解析cmd失败。


1.subprocess.Popen调用报异常:


当使用pyinstaller打成.exe文件安装后


使用p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)


报WindowsError:[Error 6]异常


单独使用subprocess.check_output(cmd)同样报此异常。


奇怪的是,直接用源码测试执行时系统完全没有任何问题。


后来才发现,当使用pyinstaller打包时,Popen应该如下初始化:


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


msg = ''


for line in p.stdout.readlines():


msg += line


status = p.wait()


这样就可以轻松获取指令执行返回的状态值和信息了。


2.Multiprocessing


系统在linux下多进程正常执行,但用pyinstaller打包后在windows下,pool.apply_async(...)多进程启动没有任何反应。在网上找了很久发现:


代码中直接使用标准库中的multiprocessing.Process和multiprocessing.Pool,在打包成可执行程序后会创建进程失败。对于pyinstaller的one-directory模式,只要再程序的最开始调用multiprocessing. freeze_support()就可以了,但对于one-file模式,还需要使用下面修改后的Process和Pool。


import multiprocessing.forking


import multiprocessing.pool


import os


import sys


class _Popen(multiprocessing.forking.Popen):


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


if hasattr(sys, 'frozen'):


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


try:


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


finally:


if hasattr(sys, 'frozen'):


if hasattr(os, 'unsetenv'):


os.unsetenv('_MEIPASS2')


else:


os.putenv('_MEIPASS2', '')


class Process(multiprocessing.Process):


_Popen = _Popen


class Pool(multiprocessing.pool):


Process = Process


3.此外,pyinstaller只支持ascii,打包后可执行文件路径不能有中文。


参考文章:


https://stackoverflow.com/questions/24944558/pyinstaller-built-windows-exe-fails-with-multiprocessing


https://www.aichengxu.com/view/29937




转载自:https://blog.sina.com.cn/s/blog_b1e0a3740102vpeb.html



评论
热度(2)

© redboy | Powered by LOFTER