0

我有一个 python cgi 脚本,它通过子进程一遍又一遍地运行应用程序(几千次)。我不断收到同样的错误...

Traceback (most recent call last):
  File "/home/linuser/Webpages/cgi/SnpEdit.py", line 413, in <module>
    webpage()
  File "/home/linuser/Webpages/cgi/SnpEdit.py", line 406, in main
    displayOmpResult(form['odfFile'].value)
  File "/home/linuser/Webpages/cgi/SnpEdit.py", line 342, in displayContainerDiv
    makeSection(position,sAoiInput)
  File "/home/linuser/Webpages/cgi/SnpEdit.py", line 360, in displayData
    displayTable(i,j,lAmpAndVars,dOligoSet[key],position)
  File "/home/linuser/Webpages/cgi/SnpEdit.py", line 247, in displayTable
    p = subprocess.Popen(['/usr/bin/pDat',sInputFileLoc,sOutputFileLoc],stdout=fh, stderr=fh)
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1039, in _execute_child
    errpipe_read, errpipe_write = os.pipe()
OSError: [Errno 24] Too many open files

导致它的功能如下。

def displayTable(sData):

    # convert the data to the proper format
    sFormattedData = convertToFormat(sData)

    # write the formatted data to file
    sInputFile = tempfile.mkstemp(prefix='In_')[1]
    fOpen = open(sInputFile,'w')
    fOpen.write(sFormattedData)
    fOpen.close()

    sOutputFileLoc = sInputFile.replace('In_','Out_')

    # run app, requires two files; an input and an output
    # temp file to holds stdout stderr of subprocess
    fh = tempfile.TemporaryFile(mode='w',dir=tempfile.gettempdir())
    p = subprocess.Popen(['/usr/bin/pDat',sInputFileLoc,sOutputFileLoc],stdout=fh, stderr=fh)
    p.communicate()
    fh.close()

    # open output file and print parsed data into a list of dictionaries
    sOutput = open(sOutputFileLoc).read()
    lOutputData = parseOutput(sOutput)

    displayTableHeader(lOutputData)
    displaySimpleTable(lOutputData)

据我所知,我正在正确关闭文件。当我跑...

import resource
print resource.getrlimit(resource.RLIMIT_NOFILE)

我得到...

(1024, 1024)

我必须增加这个值吗?我读到子进程打开了几个文件描述符。我尝试添加“close_fds = True”,并尝试在创建文件时使用 with 语句,但结果是相同的。我怀疑问题可能出在我正在处理的应用程序 pDat 上,但这个程序是由其他人制作的。它需要两个输入;输入文件和您希望将输出文件写入的位置。我怀疑它可能没有关闭它创建的输出文件。除此之外,我看不出我可能做错了什么。有什么建议么?谢谢。

编辑:我在运行 python 2.6.5 和 apache 2.2.14 的 ubuntu 10.04

4

2 回答 2

1

而不是这个...

sInputFile = tempfile.mkstemp(prefix='In_')[1]
fOpen = open(sInputFile,'w')
fOpen.write(sFormattedData)
fOpen.close()

我应该这样做...

iFileHandle,sInputFile = tempfile.mkstemp(prefix='In_')
fOpen = open(sInputFile,'w')
fOpen.write(sFormattedData)
fOpen.close()
os.close(iFileHandle)

mkstemp 函数对文件进行操作系统级别的句柄,而我没有关闭它们。该解决方案在此处进行了更详细的描述... http://www.logilab.org/blogentry/17873

于 2012-09-11T19:34:14.867 回答
0

您想添加close_fds=Truepopen通话中(以防万一)。

然后,这里:

# open output file and print parsed data into a list of dictionaries
    sOutput = open(sOutputFileLoc).read()
    lOutputData = parseOutput(sOutput)

...我可能记错了,但除非您使用with语法,否则我不认为输出文件描述符已关闭。

更新:主要问题是您需要知道哪些文件是打开的。在 Windows 上,这需要类似 Process Explorer 的东西。在 Linux 中它更简单一些。您只需从命令行调用 CGI,或者确保只有一个psCGI 实例正在运行,然后使用命令获取其 pid 。

获得 pid 后,ls -la/proc/<PID>/fd目录的内容运行 a。所有打开的文件描述符都将在那里,以及它们指向的文件的名称。知道某某文件被打开了 377 次,这对于找出文件的确切打开位置(但未关闭)大有帮助。

于 2012-08-30T13:51:57.267 回答