os.close(0)&之间的区别sys.stdin.close() [英] Difference between os.close(0) & sys.stdin.close()

查看:178
本文介绍了os.close(0)&之间的区别sys.stdin.close()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一些Python代码,这是从Apache调用的CGI脚本。



代码要做的第一件事是(我认为)尝试使用以下命令关闭stdin / stdout / stderr:

 对于[0,1,2]中的fd:
尝试:
os.close(fd)
例外:
通过

通常这是可行的,但是如果它们没有打开,我会得到一个 python.exe有停止工作,出现问题导致程序无法正常工作错误消息(Win32异常)。



问题对:




  • 通过os.close关闭有什么区别(描述符编号)和sys.stdin.close()等。

  • 假设我应该通过两种机制关闭,如何检查描述符是否确实打开(即调用os.close不会导致Python崩溃)


解决方案

我不确定,但是我敢打赌, os.close()只是操作系统的 close()系统调用的python包装器。 Python文件对象为用户处理了一些很酷的事情,例如数据的内部缓冲等等,这在调用其 close()方法时会得到照顾。



最终,操作系统的 close()系统调用将在File对象的文件描述符中调用。因此,在某个时候调用 sys.stdin.close()等效于调用 os.close(sys.stdin.fileno())



根据文档,您可以在多个文件上调用 close()方法时间和Python无关。文件对象甚至提供了 closed 属性来检查文件是否打开:

 >> import os 

>> f = open(os.devnull)
>> f.close()
>> f.close()
>> f.close()
>> f.close()
>> f.close()
>>打印f.closed

如果可能的话,我建议调用sys.FD的 close()方法,因为它更干净,更Python化。



Update



在查看python的源代码之后,我发现了文件对象( fileobjects.c ):



< pre $ = lang-c prettyprint-override> 静态PyObject *
file_close(PyFileObject * f)
{
PyObject * sts = close_the_file(f);
if(sts){
PyMem_Free(f-> f_setbuf);
f-> f_setbuf = NULL;
}
return sts;
}

PyDoc_STRVAR(close_doc,
close()->无或(也许是)整数。关闭文件。\n
\ \n
将数据属性.closed设置为True。关闭的文件无法用于\n
进一步的I / O操作。close()可能会多次调用而没有\ n
错误。某些类型的文件对象(例如,由popen()打开) n
关闭时可能返回退出状态。);



在close_the_file(f)内部;



<上课前= lang-c prettyprint-override> 静态PyObject *
close_the_file(PyFileObject * f)
{
int sts = 0;
int(* local_close)(文件*);
文件* local_fp = f-> f_fp;
char * local_setbuf = f-> f_setbuf;
if(local_fp!= NULL){
local_close = f-> f_close; //获取fs close()方法

/ *此处存在一些保密性... * /

f-> f_fp = NULL;
if(local_close!= NULL){
f-> f_setbuf = NULL;
Py_BEGIN_ALLOW_THREADS
errno = 0;
sts =(** local_close)(local_fp); //调用close()
Py_END_ALLOW_THREADS
f-> f_setbuf = local_setbuf;
if(sts == EOF)
返回PyErr_SetFromErrno(PyExc_IOError);
if(sts!= 0)
返回PyInt_FromLong((long)sts);
}
}
Py_RETURN_NONE;
}



什么是文件的close()方法?



 静态PyObject * 
fill_file_fields(PyFileObject * f,FILE * fp,PyObject *名称,char * mode,
int(* close)(FILE *))
{
...
f-> f_close =关闭;
...
}



对于os模块(使用 posixmodule.c ):



  / *此文件还用于Windows NT / MS-Win和OS / 2。在那种情况下,
模块实际上称自己为 nt或 os2,而不是 posix,并且有一些
函数未实现或以不同方式实现。源
假定对于Windows NT,宏 MS_WINDOWS的定义独立于所使用的编译器
。不同的编译器定义了自己的功能
测试宏,例如 __BORLANDC__或 _MSC_VER。对于OS / 2,应定义编译器
独立宏PYOS_OS2。在OS / 2上,默认的
编译器假定为IBM的VisualAge C ++(VACPP)。 PYCC_GCC用作
作为gcc到OS / 2的EMX端口的编译器特定的宏。 * /

PyDoc_STRVAR(posix_close__doc__,
close(fd)\n\n\
关闭文件描述符(用于低级别IO)。);

/ *
函数名末尾的下划线避免了与libc
函数posix_close的名称冲突。
* /
静态PyObject *
posix_close_(PyObject * self,PyObject * args)
{
int fd,res;
if(!PyArg_ParseTuple(args, i:close,& fd))
返回NULL;
if(!_PyVerify_fd(fd))
return posix_error();
Py_BEGIN_ALLOW_THREADS
res = close(fd); //关闭文件描述符fd
Py_END_ALLOW_THREADS
if(res <0)
return posix_error(); //也可以引发OSError()
Py_INCREF(Py_None);
返回Py_None;
}



如果文件描述符已关闭,则 OSError 引发:



 静态PyObject * 
posix_error(void)
{
return PyErr_SetFromErrno(PyExc_OSError);
}

因此,调用 os.close(fd)如果在同一文件描述符上调用两次,应引发OSError。调用 file.close()最终会调用 fclose(FILE * f)并将处理多次。 / p>

I'm working on some Python code which is a CGI script called from Apache.

The first thing the code does is (I believe) attempt to close stdin/stdout/stderr with the following:

    for fd in [0, 1, 2]:
    try:
        os.close(fd)
    except Exception:
        pass

Normally this works, however if they're not open, I get a "python.exe has stopped working", "A problem caused the program to stop working correctly" error message (Win32 exception).

Couple of questions:

  • What's the difference between closing via os.close(descriptor number) and sys.stdin.close() etc.
  • Assuming I should be closing via both mechanisms, how can I check that the descriptor is actually open (i.e. invoking os.close won't cause Python to crash)

解决方案

I don't know for sure, but I would bet that os.close() is just a python wrapper for the OS's close() system call. Python file objects handle some cool stuff for the user like internal buffering of data and whatnot and this is taken care of when calling its close() method.

Eventually, the OS's close() system call will be called on the File object's file descriptor. So, calling sys.stdin.close() at some point is equivalent to calling os.close(sys.stdin.fileno())

According to the docs, you can call the close() method on a file multiple times and Python won't care. File objects even provide an attribute, closed to check if a file is open or not:

>>> import os

>>> f = open(os.devnull)
>>> f.close()
>>> f.close()
>>> f.close()
>>> f.close()
>>> f.close()
>>> print f.closed
True

If possible, I would suggest calling the sys.FD's close() method as it's cleaner and more pythonic.

Update

After looking at the source for python, I found this for file objects (fileobjects.c):

static PyObject *
file_close(PyFileObject *f)
{
    PyObject *sts = close_the_file(f);
    if (sts) {
        PyMem_Free(f->f_setbuf);
        f->f_setbuf = NULL;
    }
    return sts;
}

PyDoc_STRVAR(close_doc,
"close() -> None or (perhaps) an integer.  Close the file.\n"
"\n"
"Sets data attribute .closed to True.  A closed file cannot be used for\n"
"further I/O operations.  close() may be called more than once without\n"
"error.  Some kinds of file objects (for example, opened by popen())\n"
"may return an exit status upon closing.");

Inside close_the_file(f);

static PyObject *
close_the_file(PyFileObject *f)
{
    int sts = 0;
    int (*local_close)(FILE *);
    FILE *local_fp = f->f_fp;
    char *local_setbuf = f->f_setbuf;
    if (local_fp != NULL) {
        local_close = f->f_close; // get fs close() method

        /* SOME CONCURRENCY STUFF HERE... */

        f->f_fp = NULL;
        if (local_close != NULL) {
            f->f_setbuf = NULL;
            Py_BEGIN_ALLOW_THREADS
            errno = 0;
            sts = (*local_close)(local_fp); // Call the close()
            Py_END_ALLOW_THREADS
            f->f_setbuf = local_setbuf;
            if (sts == EOF)
                return PyErr_SetFromErrno(PyExc_IOError);
            if (sts != 0)
                return PyInt_FromLong((long)sts);
        }
    }
    Py_RETURN_NONE;
}

What is the file's close() method?

static PyObject *
fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,
                 int (*close)(FILE *))
{
    ...
    f->f_close = close;
    ...
}

And for the os module (which uses posixmodule.c):

/* This file is also used for Windows NT/MS-Win and OS/2.  In that case the
   module actually calls itself 'nt' or 'os2', not 'posix', and a few
   functions are either unimplemented or implemented differently.  The source
   assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
   of the compiler used.  Different compilers define their own feature
   test macro, e.g. '__BORLANDC__' or '_MSC_VER'.  For OS/2, the compiler
   independent macro PYOS_OS2 should be defined.  On OS/2 the default
   compiler is assumed to be IBMs VisualAge C++ (VACPP).  PYCC_GCC is used
   as the compiler specific macro for the EMX port of gcc to OS/2. */

PyDoc_STRVAR(posix_close__doc__,
"close(fd)\n\n\
Close a file descriptor (for low level IO).");

/*
The underscore at end of function name avoids a name clash with the libc
function posix_close.
*/
static PyObject *
posix_close_(PyObject *self, PyObject *args)
{
    int fd, res;
    if (!PyArg_ParseTuple(args, "i:close", &fd))
        return NULL;
    if (!_PyVerify_fd(fd))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
    res = close(fd);  // close the file descriptor fd
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error(); // AKA raise OSError()
    Py_INCREF(Py_None);
    return Py_None;
}

If the file descriptor has already been closed, then an OSError is raised:

static PyObject *
posix_error(void)
{
    return PyErr_SetFromErrno(PyExc_OSError);
}

So, calling os.close(fd) should raise an OSError if called twice on the same file descriptor. Calling file.close() eventually calls fclose(FILE *f) and will handle it being called multiple times.

这篇关于os.close(0)&amp;之间的区别sys.stdin.close()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆