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

发布于 2024-08-17 09:13:20 字数 2626 浏览 3 评论 0原文

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

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

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

1)如果 W:\library.zip 包含 .pyc 文件的唯一副本,我得到 ZipImportError:无法解压数据; zlib 不可用(废话,考虑到 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)。

编辑2:事实上,根据this,有是 Python 解释器中的 sys.path 与 Py2exe 可执行文件中的 sys.path 之间的差异。具体来说,sys.path 仅包含一个条目:共享代码存档的完整路径名。 废话。没有后备方案吗?甚至不是当前的工作目录?我尝试将 W:\ 添加到 PATH,但 py2exe 不符合任何定位系统库的标准,因此它不起作用。

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

W:\\library.zip\<模块>.

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

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

有什么想法吗?我有一个,那就是规范路径 sys.path ..遗憾的是我需要 os 来实现这一点。另一种方法是再次将 os.getenv('PATH')os.getenv('PYTHONPATH') 附加到 sys.path...,需要 操作系统模块。 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?

I'm running a py2exe-compiled python program from one server machine on a number of client machines (mapped to a network drive on every machine, say W:).

For Windows XP and later machines, have so far had zero problems with Python picking up W:\python23.dll (yes, I'm using Python 2.3.5 for W98 compatibility and all that). It will then use W:\zlib.pyd to decompress W:\library.zip containing all the .pyc files like os and such, which are then imported and the program runs no problems.

The issue I'm getting is on some Windows 98 SE machines (note: SOME Windows 98 SE machines, others seem to work with no apparent issues). What happens is, the program runs from W:, the W:\python23.dll is, I assume, found (since I'm getting Python ImportErrors, we'd need to be able to execute a Python import statement), but a couple of things don't work:

1) If W:\library.zip contains the only copy of the .pyc files, I get
ZipImportError: can't decompress data; zlib not available (nonsense, considering W:\zlib.pyd IS available and works fine with the XP and higher machines on the same network).

2) If the .pyc files are actually bundled INSIDE the python exe by py2exe, OR put in the same directory as the .exe, OR put into a named subdirectory which is then set as part of the PYTHONPATH variable (e.g W:\pylib), I get ImportError: no module named os (os is the first module imported, before sys and anything else).

Come to think of it, sys.path wouldn't be available to search if os was imported before it maybe? I'll try switching the order of those imports but my question still stands: Why is this a sporadic issue, working on some networks but not on others? And how would I force Python to find the files that are bundled inside the very executable I run?
I have immediate access to the working Windows 98 SE machine, but I only get access to the non-working one (a customer of mine) every morning before their store opens.

Thanks in advance!


EDIT: Okay, big step forward. After debugging with PY2EXE_VERBOSE, the problem occurring on the specific W98SE machine is that it's not using the right path syntax when looking for imports. Firstly, it doesn't seem to read the PYTHONPATH environment variable (there may be a py2exe-specific one I'm not aware of, like PY2EXE_VERBOSE).

Secondly, it only looks in one place before giving up (if the files are bundled inside the EXE, it looks there. If not, it looks in library.zip).

EDIT 2: In fact, according to this, there is a difference between the sys.path in the Python interpreter and that of Py2exe executables. Specifically, sys.path contains only a single entry: the full pathname of the shared code archive. Blah. No fallbacks? Not even the current working directory? I'd try adding W:\ to PATH, but py2exe doesn't conform to any sort of standards for locating system libraries, so it won't work.

Now for the interesting bit. The path it tries to load atexit, os, etc. from is:

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

Note the single slash after library.zip, but the double slash after the drive letter (someone correct me if this is intended and should work). It looks like if this is a string literal, then since the slash isn't doubled, it's read as an (invalid) escape sequence and the raw character is printed (giving W:\library.zipos.pyd, W:\library.zipos.dll, ... instead of with a slash); if it is NOT a string literal, the double slash might not be normpath'd automatically (as it should be) and so the double slash confuses the module loader. Like I said, I can't just set PYTHONPATH=W:\\library.zip\\ because it ignores that variable.

It may be worth using sys.path.append at the start of my program but hard-coding module paths is an absolute LAST resort, especially since the problem occurs in ONE configuration of an outdated OS.

Any ideas? I have one, which is to normpath the sys.path.. pity I need os for that. Another is to just append os.getenv('PATH') or os.getenv('PYTHONPATH') to sys.path... again, needing the os module. The site module also fails to initialise, so I can't use a .pth file.

I also recently tried the following code at the start of the program:

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

But it can't load linecache.pyc, or anything else for that matter; it can't actually execute those commands from the looks of things. Is there any way to use built-in functionality which doesn't need linecache to modify the sys.path dynamically? Or am I reduced to hard-coding the correct sys.path?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

当爱已成负担 2024-08-24 09:13:20

这不是直接答案,但可能有一些帮助。您熟悉 Python 中的 -v 选项吗?输入 python -h 了解更多信息。请注意,与 py2exe 脚本的 PYTHONVERBOSE 环境变量等效的是 PY2EXE_VERBOSE,除了 作者的这篇文章。显然它可以取 1 或 2 的值,基本上类似于 -v-vv,尽管这与 PYTHONVERBOSE 的工作原理

另请注意您的 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 信息链接。

This isn't a direct answer, but possibly some help. Are you familiar with the -v option in Python. Type python -h to learn more. Note the equivalent to the PYTHONVERBOSE environment variable for py2exe'd scripts is PY2EXE_VERBOSE, as described almost nowhere except in this post by its author. Apparently it can take values of 1 or 2, basically like -v and -vv, though that's slightly different from how PYTHONVERBOSE works.

Note also about your sys.path idea: whether you have imported sys already or not would have no effect on whether you could import os. That is, the Python path (visible in sys.path) is always available, in the sense that it reflects an internal feature of the interpreter which is there whether you've imported the sys module or not.

As with a number of other modules, sys is built-in, so it should always be importable even if your app is almost totally crippled. If it will help, you may be able to use sys.builtin_module_names to see what they are for your version of Python. If the interpreter is running at all that information would be available, so the following may be the smallest useful program you can make to see what you've got:

import sys
print sys.builtin_module_names

Also, I'd advise against trying anything fancy like bundling the .pyc files inside the .exe. You've already got enough working against you being stuck supporting Win98, and if I were you I'd go for the simplest approach that would let me get the job done and move on to more interesting areas. If you could just install Python normally and run from source, you should definitely consider it! :)

Edited to include link to PY2EXE_VERBOSE info per comment by darvids0n.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文