我正在研究一些Python代码,这是一个从Apache调用的CGI脚本。
代码所做的第一件事是(我相信)尝试使用以下内容关闭stdin / stdout / stderr:
for fd in [0, 1, 2]:
try:
os.close(fd)
except Exception:
pass
通常这可行,但是如果它们没有打开,我得到“python.exe已停止工作”,“一个问题导致程序停止正常工作”错误消息(Win32异常)。
几个问题:
答案 0 :(得分:4)
我不确定,但我敢打赌,os.close()
只是操作系统close()
系统调用的python包装器。 Python文件对象为用户处理一些很酷的东西,比如内部缓冲数据和诸如此类的东西,这在调用它的close()
方法时会得到解决。
最终,将在File对象的文件描述符上调用OS的close()
系统调用。因此,在某个时候调用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()
>>> print f.closed
True
如果可能的话,我会建议调用sys.FD的close()
方法,因为它更干净,更蟒蛇。
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.");
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;
}
static PyObject *
fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,
int (*close)(FILE *))
{
...
f->f_close = close;
...
}
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;
}
OSError
:static PyObject *
posix_error(void)
{
return PyErr_SetFromErrno(PyExc_OSError);
}
因此,如果在同一文件描述符上调用两次,则调用os.close(fd)
会引发OSError。调用file.close()
最终会调用fclose(FILE *f)
,并会多次调用它。