Python 文件对象是真实文件吗?
Is a Python File object a real file?
在Python中,一个文件对象可能指向一个真实的文件、stdin、stdout、stderr,甚至是其他东西。因此它可以是 类文件,或 真实文件,如 file.flush.
所述
如何知道一个文件是不是真实文件?我找到了一些猜测的方法,但 none 似乎真的很可靠:
file not in [sys.stdin, sys.stdout, sys.stderr]
-- 看起来最安全,但仅适用于那些标准类型,不是非常通用的解决方案。
os.path.isfile(file.name)
-- 看起来很安全,但我猜如果在某些创建模式下打开新文件可能无法工作。
file.fileno() == 0
-- 这假定方法未实现,默认实现 returns 0,正常实现永远不会 return 0.
file.name.startswith('<')
-- 这实际上假设文件系统不允许在文件名中使用 <
。
为什么我需要知道这个,因为我想提前关闭它,使用 with file as f:
可能会关闭 stdin/stdout,这听起来是个坏主意。
一般来说,您应该只对称地使用 with ... as f:
,也就是说,使用您 open
或在 with
语句中获得的文件句柄。
在 UNIX 上,您可以检查 .fileno()
- 0 代表标准输入,1 代表标准输出,2 代表标准错误;通常你不应该关闭这些流,因为真的没有办法再重新打开它们了。
file.name
并不是真正的 100% 证明方法,因为许多流可以有一个名称,即使它们不是真实的文件,并且该特殊名称可能与磁盘上的现有文件冲突:
>>> import os.path
>>> os.path.exists(sys.stdin.name)
True
>>> sys.stdin.name
'<stdin>'
(提示,就在我做之前 touch '<stdin>'
)
此外,在 UNIX 中,通常在打开临时文件后立即取消链接,因此它们不再存在;另一方面,即使是现有文件在打开后也可能被 重命名,因此原始名称并不存在。
如果你想知道一个标准流是否被重定向到一个文件,你可以这样做:
>>> import os
>>> import stat
>>> stat.S_ISREG(os.fstat(sys.stdout.fileno()).st_mode)
False
S_ISREG
returns True
如果模式描述的是普通文件(此处输出到终端,因此为 False);同样,您可以使用 isatty
:
查看是否有任何文件被重定向到 terminal
>>> os.isatty(sys.stdout.fileno())
True
来自 Python 的套接字库的 This part 可能会有帮助(其中 file
是一个文件对象):
try:
fileno = file.fileno()
except (AttributeError, io.UnsupportedOperation) as err:
raise _GiveupOnSendfile(err) # not a regular file
try:
fsize = os.fstat(fileno).st_size
except OSError as err:
raise _GiveupOnSendfile(err) # not a regular file
在Python中,一个文件对象可能指向一个真实的文件、stdin、stdout、stderr,甚至是其他东西。因此它可以是 类文件,或 真实文件,如 file.flush.
所述如何知道一个文件是不是真实文件?我找到了一些猜测的方法,但 none 似乎真的很可靠:
file not in [sys.stdin, sys.stdout, sys.stderr]
-- 看起来最安全,但仅适用于那些标准类型,不是非常通用的解决方案。os.path.isfile(file.name)
-- 看起来很安全,但我猜如果在某些创建模式下打开新文件可能无法工作。file.fileno() == 0
-- 这假定方法未实现,默认实现 returns 0,正常实现永远不会 return 0.file.name.startswith('<')
-- 这实际上假设文件系统不允许在文件名中使用<
。
为什么我需要知道这个,因为我想提前关闭它,使用 with file as f:
可能会关闭 stdin/stdout,这听起来是个坏主意。
一般来说,您应该只对称地使用 with ... as f:
,也就是说,使用您 open
或在 with
语句中获得的文件句柄。
在 UNIX 上,您可以检查 .fileno()
- 0 代表标准输入,1 代表标准输出,2 代表标准错误;通常你不应该关闭这些流,因为真的没有办法再重新打开它们了。
file.name
并不是真正的 100% 证明方法,因为许多流可以有一个名称,即使它们不是真实的文件,并且该特殊名称可能与磁盘上的现有文件冲突:
>>> import os.path
>>> os.path.exists(sys.stdin.name)
True
>>> sys.stdin.name
'<stdin>'
(提示,就在我做之前 touch '<stdin>'
)
此外,在 UNIX 中,通常在打开临时文件后立即取消链接,因此它们不再存在;另一方面,即使是现有文件在打开后也可能被 重命名,因此原始名称并不存在。
如果你想知道一个标准流是否被重定向到一个文件,你可以这样做:
>>> import os
>>> import stat
>>> stat.S_ISREG(os.fstat(sys.stdout.fileno()).st_mode)
False
S_ISREG
returns True
如果模式描述的是普通文件(此处输出到终端,因此为 False);同样,您可以使用 isatty
:
>>> os.isatty(sys.stdout.fileno())
True
This part 可能会有帮助(其中 file
是一个文件对象):
try:
fileno = file.fileno()
except (AttributeError, io.UnsupportedOperation) as err:
raise _GiveupOnSendfile(err) # not a regular file
try:
fsize = os.fstat(fileno).st_size
except OSError as err:
raise _GiveupOnSendfile(err) # not a regular file