gpt4 book ai didi

python - os.close(0) 和 sys.stdin.close() 的区别

转载 作者:行者123 更新时间:2023-11-28 21:54:28 25 4
gpt4 key购买 nike

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

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

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

这通常有效,但如果它们未打开,我会收到“python.exe 已停止工作”、“导致程序停止正常工作的问题”错误消息(Win32 异常)。

几个问题:

  • 通过 os.close(descriptor number) 和 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()
>>> print f.closed
True

如果可能,我会建议调用 sys.FD 的 close() 方法,因为它更简洁,更符合 Python 风格。

更新

在查看了 python 的源代码后,我找到了文件对象 (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.");

在 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;
}

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

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

对于 os 模块(使用 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) 并将处理它被多次调用。

关于python - os.close(0) 和 sys.stdin.close() 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24173998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com