解决tkinter中调用NodeJS用pyintaller打包成无命令行窗口后运行过程中显示NodeJS黑框的问题

解决tkinter中调用NodeJS用pyintaller打包成无命令行窗口后运行过程中显示NodeJS黑框的问题

前言

最近做一个python项目,项目中调用了NodeJS中的一段代码,用tkinter做GUI然后pyintaller打包成无命令行窗口后运行过程中显示NodeJS黑框,客户不接受。于是网上查找各种办法,但是都只有pyintaller打包时用-w/–noconsole类似的回答,该方法只能取消python程序的黑框,NodeJS的无法取消。于是查看execjs的源代码,终于解决此问题。

测试代码

from tkinter import *
import os
import execjs


def get_js(fileNme):
    # jscript = execjs.get("Node")
    # jscript = execjs.get()
    with open(fileNme, 'r', encoding='utf-8')as f:
        content = f.read()
    js = execjs.compile(content)
    return js


def get_data(entry):
    js = get_js("测试.js")

    var.set(str(js.call("getData", "1")))


root = Tk()
button = Button(root, text="点击", command=lambda: get_data(entry))
button.pack()
var = StringVar()
entry = Entry(root, textvariable=var)
entry.pack()
root.mainloop()

测试运行

改成 .pyw 直接运行,发现 node 弹窗一闪即逝。如下图:
在这里插入图片描述

反查源代码

  • 经测试发现每次调用 .call 的时候都会弹窗
  • 找到.call打断点,一步步调试,最终定位到 execjs库中的_external_runtime.py文件下的函数_exec_with_pipe
        def _exec_with_pipe(self, source):
            cmd = self._runtime._binary()

            p = None
            try:
                p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=self._cwd, universal_newlines=True)
                # 不显示调用黑框
                # p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=self._cwd, universal_newlines=True, shell=True)
                input = self._compile(source)
                if six.PY2:
                    input = input.encode(sys.getfilesystemencoding())
                stdoutdata, stderrdata = p.communicate(input=input)
                ret = p.wait()
            finally:
                del p

            self._fail_on_non_zero_status(ret, stdoutdata, stderrdata)
            return stdoutdata
  • 网上一查发现Popen为python调用cmd的函数,应该就是他了,想办法让调用的时候不显示命令行就行了,Popen有没有不显示黑框的参数呢,结果还真有。
    参考博文:python中的subprocess.Popen()使用
    在这里插入图片描述

  • 很明显,只要将 Popen 创建对象的时候加上 shell=True 就可以了,即

p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=self._cwd, universal_newlines=True)

改为

p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=self._cwd, universal_newlines=True, shell=True)

总结

  • 在python中只要调用了cmd的地方,在用pyinstaller打包成无控制台显示(-w/–noconsole)的时候都会出现黑框
  • 不用(-w/–noconsole)打包的时候不出现黑框是因为程序自身就在控制台中运行
  • 凡是通过Popen调用cmd的所有代码,都可以这样修改取消控制台输出。
  • 53
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值