简体   繁体   English

使用子进程的CGI脚本上的python errno 24

[英]python errno 24 on cgi script using subprocess

I have a python cgi script that runs an application via subprocess over and over again (several thousand times). 我有一个python cgi脚本,可以通过子进程一遍又一遍地运行应用程序(数千次)。 I keep getting the same error... 我不断收到相同的错误...

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

The function causing it is below. 导致它的功能如下。

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)

As far as I can tell, I'm closing the files properly. 据我所知,我正在正确关闭文件。 When I run... 我跑步的时候

import resource
print resource.getrlimit(resource.RLIMIT_NOFILE)

I get... 我知道了

(1024, 1024)

Do I have to increase this value? 我必须增加这个值吗? I read that subprocess opens several file descriptors. 我读到子进程会打开几个文件描述符。 I tried adding "close_fds = True" and I tried using the with statement when creating my file but the result was the same. 我尝试添加“ close_fds = True”,并且在创建文件时尝试使用with语句,但结果相同。 I suspect the problem may be with the application that I'm subprocessing, pDat, but this program was made by someone else. 我怀疑问题可能出在我正在子处理的应用程序pDat上,但该程序是由其他人制作的。 It requires two inputs; 它需要两个输入; an input file and the location of where you want the output file written to. 输入文件以及要将输出文件写入的位置。 I suspect it may not be closing the output file that it creates. 我怀疑它可能无法关闭其创建的输出文件。 Aside from this, I can't see what I might be doing wrong. 除此之外,我看不到我可能做错了什么。 Any suggestions? 有什么建议么? Thanks. 谢谢。

EDIT: I'm on ubuntu 10.04 running python 2.6.5 and apache 2.2.14 编辑:我在运行python 2.6.5和apache 2.2.14的ubuntu 10.04上

Instead of this... 代替这个...

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

I should have done this... 我应该做的...

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

The mkstemp function makes OS level handles to a file and I wasn't closing them. mkstemp函数使操作系统级别的文件处理成为可能,但我没有关闭它们。 The solution is described in more detail here... http://www.logilab.org/blogentry/17873 该解决方案在此处有更详细的描述... http://www.logilab.org/blogentry/17873

You want to add close_fds=True to the popen call (just in case). 您想将close_fds=True添加到popen调用中(以防万一)。

Then, here: 然后,在这里:

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

...I might remember wrong, but unless you use the with syntax, I do not think that the output file descriptor has been closed. ...我可能记得错了,但是除非您使用with语法,否则我不认为输出文件描述符已关闭。

UPDATE : the main problem is that you need to know which files are open . 更新 :主要问题是您需要知道打开了哪些文件 On Windows this would require something like Process Explorer. 在Windows上,这需要诸如Process Explorer之类的东西。 In Linux it's a bit simpler; 在Linux中,它要简单一些。 you just have to invoke the CGI from command line, or be sure that there is only one instance of the CGI running, and fetch its pid with ps command. 您只需要从命令行调用CGI,或者确保只有一个 CGI实例正在运行,并使用ps命令获取其pid。

Once you have the pid, run a ls -la on the content of the /proc/<PID>/fd directory. 有了pid后,请在/proc/<PID>/fd目录的内容上运行ls -la All open file descriptors will be there, with the name of the files they point to. 所有打开的文件描述符都将在其中,并带有它们指向的文件的名称。 Knowing that file so-and-so is opened 377 times, that goes a long way towards finding out where exactly that file is opened (but not closed). 明知文件某某这样被打开377倍,这大大有助于找出究竟在何处打开那个文件(但不封闭)很长的路要走。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM