7

我的 python 程序在 Windows HPC 2008 环境中准备输入、运行外部 FORTRAN 代码并处理输出。它工作得很好,除非代码在 1042-1045 次之间执行外部程序(通常问题会更早收敛)。在这些情况下,我得到一个例外:

WindowsError:[错误 206] 文件名或扩展名太长

但是,文件名的路径不会随时间增长。它只是清理目录并再次运行。

这是代码:

inpF = open(inName)
outF = open(localOutName,'w')
p = subprocess.Popen(pathToExe,shell=False,stdin=inpF,stdout=outF,cwd=runPath)
stdout, stderr = p.communicate()
outF.close()
inpF.close()

pathToExe 是指向 UNC 位置的常量字符串(例如 \\server\shared\program.exe),stdin 是在本地驱动器上以只读模式打开的文件,stdout 是在本地驱动器上以写入模式打开的文件,而 cwd 是 C:\ 驱动器上的本地路径。根据这篇有点相关的帖子,我已经确认 subprocess 的所有参数都不超过 80 个字符,即使限制应该是 32,768 。

我究竟做错了什么?不知何故,有些东西在积累,只有当我跑一千次时才会成为问题。

更新:

为了测试“打开的文件太多”假设,我做了一个非常小的示例,它使用不同的可执行文件运行得非常快。这里的主要区别是标准输入和标准输出在这里只是空文件,而在前一种情况下,它们都是大文件。在这种情况下,代码运行 2000 次就很好,而之前的代码在 ~1042 处失败。所以不仅仅是有那么多文件。也许有太多的大文件打开?

import subprocess
for i in range(nRuns):
    if not (i % (nRuns/10.0)):
        print('{0:.2}% complete'.format(i/float(nRuns)*100))
    inpF=open('in.txt')
    outF=open('out.txt','w')
    p = subprocess.Popen('isotxsmerge.exe',shell=False,stdin=inpF,
                                 stdout=outF,cwd='.')
    stdout, stderr = p.communicate()
    outF.close()
    inpF.close()
4

2 回答 2

4

嗯....实际上,我认为错误消息文本是红鲱鱼。我不确定,但在我看来,发生的事情很可能是您的文件句柄用完了。从各种来源来看,规范文件句柄限制似乎在 2048 个文件左右……奇怪的是在 2 x 1042 个子进程附近。我不知道 windows python 解释器的内部结构,但我的猜测是句柄没有足够快地被垃圾收集,即使你正在关闭文件。再一次……这只是一个猜测……但也许这是另一种思路,可能会引导你做出更有结论性和更有成效的事情。

同时,作为一种变通方法,您可以使用旧的备用方法,方法是拥有一个生成进程的调控器进程,然后生成子进程。中间子进程在它死亡之前有一个确定的生命周期(比如......它产生的子进程不超过 1000 个)。当中间子进程到期时,调速器进程启动一个新的子进程。这是一个黑客......而且是一个笨拙的......但它确实有效。(IIRC,Apache Web 服务器过去对子进程可以处理的请求数量有某种自毁限制。)

无论如何...祝你好运,编码愉快。

于 2012-05-23T19:05:14.150 回答
0

我最近在导出到外部 python 应用程序时偶然发现了这个错误。这是发生错误的示例代码:

subprocess.run([sys.executable, script_path, data_str])

这里 data_str 是一个 JSON 字符串。事实证明,我试图传递的 JSON 字符串太长导致了这个错误。

于 2021-11-29T21:16:32.110 回答