在 ubuntu 上使用 Pyinstaller 创建的可执行文件并在 SuSE12 SP4 上运行会引发 libreadline 问题

问题描述

在 ubuntu 16.04 上使用 pyinstaller 创建了一个可执行文件,并尝试在 SuSe 12 SP4 上运行它会在代码的特定部分出现错误代码是这样工作的:

  • 它是一个通过网络接收用户输入的烧瓶应用
  • 处理这些输入并创建一个 .sh 脚本并运行该 shell 脚本
  • 从 shell 脚本读取输出并将其作为返回渲染呈现给网络

该可执行文件已在 ubuntu 机器上成功创建并成功运行,没有发现任何问题,但是当我在 SuSe12 SP4 上使用此可执行文件时,它会启动,但是当它到达运行 bash 脚本的代码时,它会引发以下错误

sh: /tmp/_MEI369vhy/libreadline.so.6: no version information available (required by sh)

我真的厌倦了寻找解决方案,到目前为止已经完成了以下工作:

  • 尝试了 --onefile 和 --onedir,没有区别
  • 尝试在 SuSe12 sp4 本身上创建可执行文件,但它引发了关于未找到子进程的不同错误
  • 尝试在 Suse 上找到 libreadline.so,但没有运气
  • 尝试在 ubuntu 14 上创建环境,但依赖项错误太多

我终于没有建议了,可以在这里使用一些帮助。如果可以,请提供帮助。

环境

Python 2.7.12

Ubuntu 16.04

SuSe12 SP4

pyinstaller 3.6

P.S.如果我创建了适当的构建环境,那么作为原始 Python 代码代码在 SuSe 12 SP4 上可以完美运行

解决方法

所以,我终于在 Rokm 的帮助下解决了这个问题。上面的警告消息没有引起任何问题,但这是由于环境变量没有传递给子进程。 为了解决这个问题,我简单地做了以下事情:

###Add the following code to your existing code 
env = dict(os.environ)  # make a copy of the environment
lp_key = 'LD_LIBRARY_PATH'  # for GNU/Linux and *BSD.
lp_orig = env.get(lp_key + '_ORIG')
if lp_orig is not None:
    env[lp_key] = lp_orig  # restore the original,unmodified value
else:
    # This happens when LD_LIBRARY_PATH was not set.
    # Remove the env var as a last resort:
    env.pop(lp_key,None)

接下来,将 env 变量添加到子进程 Popen 命令。这是完整的代码供参考。此代码将为您提供命令的输出并返回代码,即命令的退出代码。此外,您不必使用任何 shelix 或任何其他东西来运行它,简单的 .strip() 命令将为您完成。希望你们觉得它有用,享受。 !!

from subprocess import Popen,PIPE,STDOUT
env = dict(os.environ)  # make a copy of the environment
lp_key = 'LD_LIBRARY_PATH'  # for GNU/Linux and *BSD.
lp_orig = env.get(lp_key + '_ORIG')
if lp_orig is not None:
    env[lp_key] = lp_orig  # restore the original,None)

cmd = raw_input('Enter your command:')
out = Popen(cmd.split(),stderr=STDOUT,stdout=PIPE,env=env)

t,y = out.communicate()[0],out.returncode
print('output : ' + str(t))
print ('Return Code : ' + str(y))

附言不幸的是,cmd.split() 在某些情况下会失败,即当一个参数有空格时,比如 cmd='/usr/bin/ls "/home/user/my directory"' 会因 cmd.split() 而失败。在这种情况下, cmd = shlex.split(cmd,posix=True) 会工作得更好。但是 shlex.split() 在捕获标准输出时会失败,因此恕我直言,没有全能解决方案