在 Windows 98 中通过网络访问 py2exe 程序会引发 ImportErrors

Posted

技术标签:

【中文标题】在 Windows 98 中通过网络访问 py2exe 程序会引发 ImportErrors【英文标题】:Accessing py2exe program over network in Windows 98 throws ImportErrors 【发布时间】:2011-01-01 20:46:00 【问题描述】:

我正在许多客户端机器上的一台服务器机器上运行一个 py2exe 编译的 python 程序(映射到每台机器上的网络驱动器,比如 W:)。

对于 Windows XP 和更高版本的机器,到目前为止,Python 拾取 W:\python23.dll 的问题为零(是的,我使用 Python 2.3.5 来兼容 W98 等等)。然后它将使用 W:\zlib.pyd 解压缩 W:\library.zip 包含所有 .pyc 文件,如 os 等,然后将其导入,程序运行没有问题。

我遇到的问题是在一些 Windows 98 SE 机器上(注意:一些 Windows 98 SE 机器,其他机器似乎没有明显问题)。发生的情况是,程序从 W: 运行,我假设找到了 W:\python23.dll(因为我得到 Python ImportErrors,我们需要能够执行 Python import 语句),但是有几件事不起作用:

1) 如果 W:\library.zip 包含 .pyc 文件的唯一副本,我会得到 ZipImportError: can't decompress data; zlib not available(废话,考虑到 W:\zlib.pyd 是可用的,并且可以在同一网络上的 XP 和更高版本的机器上正常工作)。

2) 如果 .pyc 文件实际上是由 py2exe 捆绑在 python exe 内部,或者放在与 .exe 相同的目录中,或者放在一个命名的子目录中,然后将其设置为 PYTHONPATH 变量的一部分(例如 W :\pylib),我得到ImportError: no module named os(os 是第一个导入的模块,在 sys 和其他任何东西之前)。

想一想,如果在它之前导入了 os,sys.path 将无法搜索?我将尝试切换这些导入的顺序,但我的问题仍然存在:为什么这是一个零星的问题,在某些网络上工作而不在其他网络上工作?我将如何强制 Python 找到捆绑在我运行的可执行文件中的文件? 我可以立即访问正在工作的 Windows 98 SE 机器,但我只能在每天早上在他们的商店开门之前访问不工作的机器(我的一位客户)。

提前致谢!


编辑:好的,向前迈出一大步。使用 PY2EXE_VERBOSE 调试后,特定 W98SE 机器上出现的问题是它在查找导入时没有使用正确的路径语法。首先,它似乎没有读取 PYTHONPATH 环境变量(可能有一个我不知道的特定于 py2exe 的变量,比如 PY2EXE_VERBOSE)。

其次,它在放弃之前只在一个地方查找(如果文件捆绑在 EXE 中,它会在那里查找。如果没有,它会在 library.zip 中查找)。

EDIT 2:事实上,根据this,Python 解释器中的sys.path 和Py2exe 可执行文件中的sys.path 是有区别的。具体来说,sys.path contains only a single entry: the full pathname of the shared code archive. Blah。没有退路?甚至没有当前的工作目录?我会尝试将W:\ 添加到 PATH,但 py2exe 不符合任何类型的系统库定位标准,所以它不起作用。

现在来说有趣的一点。它尝试加载atexit、os等的路径是:

W:\\library.zip\<module>.<ext>

注意 library.zip 后的单斜杠,但驱动器号后的双斜杠(如果这是有意的并且应该有效,请纠正我)。看起来如果这是一个字符串文字,那么由于斜杠没有加倍,它被读取为(无效的)转义序列并打印原始字符(给出 W:\library.zipos.pyd, W:\library.zipos.dll, ... 而不是斜杠);如果它不是字符串文字,则双斜杠可能不会自动进行规范路径(应该如此),因此双斜杠会混淆模块加载器。就像我说的,我不能只使用set PYTHONPATH=W:\\library.zip\\,因为它忽略了那个变量。

在我的程序开始时使用 sys.path.append 可能是值得的,但硬编码模块路径绝对是最后的手段,特别是因为问题发生在过时操作系统的 ONE 配置中。

有什么想法吗?我有一个,它是规范路径 sys.path.. 可惜我需要 os。另一种方法是再次将os.getenv('PATH')os.getenv('PYTHONPATH') 附加到sys.path...,需要os 模块。 site 模块也无法初始化,所以我不能使用 .pth 文件。

我最近也在程序开始时尝试了以下代码:

for pth in sys.path:
    fErr.write(pth)
    fErr.write(' to ')
    pth.replace('\\\\','\\') # Fix Windows 98 pathing issues
    fErr.write(pth)
    fErr.write('\n')

但它无法加载 linecache.pyc 或其他任何内容;它实际上无法从事物的外观上执行这些命令。有什么方法可以使用不需要 linecache 来动态修改 sys.path 的内置功能?还是我只能硬编码正确的 sys.path?

【问题讨论】:

你确定你有一个包含这些字符的字符串吗?如果这是printed,那么它们是真实的,并且双反斜杠部分可能使其成为无效路径。但是如果反斜杠在 Python 字符串中,则它们不会转义......它们仅在 string literals 中充当转义序列(即在正在编译的 Python 源代码中)。仔细检查你有什么,或者用 repr() 打印输出,这样我们就可以准确地看到里面有什么(在这种情况下,当你粘贴到这里时,包括周围的引号)。 直到周一早上他们的商店开门之前我才能访问客户的计算机,但我肯定会这样做并将结果发布在这里:) 今天早上不能上机器,因为我很忙。我将在开始时添加代码,将 \\ 替换为 sys.path 中的 \,并在明天部署:让我们看看是否可行。 现在压力已经消失了,至少。我手动添加了正确的路径,然后发现客户的W98机器太慢了。花了大约 20 秒来执行一个解析大约 6 个命令行参数并将它们发送到 C++ 程序的 python 脚本。将继续走“全C++”之路。不过,仍然想讨论在一台 W98 机器上而不是另一台机器上可能导致此问题的原因。 【参考方案1】:

这不是一个直接的答案,但可能会有所帮助。你熟悉 Python 中的-v 选项吗?输入python -h 了解更多信息。请注意,py2exe 脚本的 PYTHONVERBOSE 环境变量等效于 PY2EXE_VERBOSE,除了在 this post by its author 中几乎没有描述。显然它可以取值 1 或 2,基本上就像 -v-vv,虽然这与 how PYTHONVERBOSE works 略有不同。

还要注意您的 sys.path 想法:您是否已经导入 sys 对您是否可以导入 os 没有影响。也就是说,Python 路径(在sys.path 中可见)始终可用,因为它反映了解释器的内部特性,无论您是否导入了 sys 模块。

与许多其他模块一样,sys 是内置的,因此即使您的应用程序几乎完全瘫痪,它也应该始终可以导入。如果有帮助,您可以使用 sys.builtin_module_names 查看它们适用于您的 Python 版本。如果解释器正在运行,所有信息都将可用,那么以下可能是您可以制作的最小有用程序来查看您所拥有的内容:

import sys
print sys.builtin_module_names

另外,我建议不要尝试任何花哨的事情,比如将 .pyc 文件捆绑到 .exe 中。你已经有足够的工作来阻止你支持 Win98,如果我是你,我会选择最简单的方法,让我完成工作并进入更有趣的领域。如果您可以正常安装 Python 并从源代码运行,您绝对应该考虑它! :)

已编辑以包含指向 darvids0n 的每条评论的 PY2EXE_VERBOSE 信息的链接。

【讨论】:

不幸的是,彼得,它是硬编码的(在我无法修改的应用程序中)在命令行上运行这个 py2exe 可执行文件(传递参数等),所以我无法安装客户端计算机上的 Python。不过,感谢您的想法,我会检查目标系统上的 PYTHONVERBOSE 和 sys.builtin_module_names :) @darvids0n,调用程序可能不需要实际的 exe,在这种情况下,您可以尝试制作一个调用 Python 的“trampoline”.bat 文件使用脚本的名称和适当的参数。只是另一个想法,FWIW。 彼得,只是仔细检查了一下,调用实际上是一个 .exe,而不仅仅是程序的名称。一个拼凑的解决方案是编写一个 C++ exe 来在命令行上执行一个 .bat (可怕的、可怕的方法,但它会起作用)。希望我能在不久的将来通过用 C++ 完全重写 Python 程序来解决所有这些问题,不过,这是我的最终目标(更快,而且看起来也更稳定)。 我很快用谷歌搜索了 py2exe 的详细设置,PY2EXE_VERBOSE=1 打印导入语句的结果,PY2EXE_VERBOSE=2 打印每个导入语句的每次尝试。我会尝试在目标站点上使用它,应该让我对它在哪里寻找和不在哪里有一个很大的了解。感谢您的帮助:D 好发现!我从来不知道 py2exe 有这样的额外设置。我会在我的答案中添加一个链接以供后人参考。

以上是关于在 Windows 98 中通过网络访问 py2exe 程序会引发 ImportErrors的主要内容,如果未能解决你的问题,请参考以下文章

在android中通过wifi访问连接在本地网络上的打印机

在VB6中通过DAO优化高延迟网络上的开放访问数据库

在 Java 中通过 SSH 隧道运行远程命令

在 Qt 中通过 Windows GDI 绘图

错误 - 在 windows 10/8.1 机器中通过 anaconda 使用 python pyspark

在 Apache Spark 中通过管道运行 Windows 批处理文件