在Python中,文件对象可能指向真实文件,stdin,stdout,stderr,甚至是其他东西.因此它可以是文件,也可以是file.flush中所述的真实文件.
如何知道文件是否是真实文件?我找到了一些猜测的方法,但似乎没有一个真正可靠:
file not in [sys.stdin, sys.stdout, sys.stderr] - 似乎最安全但仅适用于那些标准类型,而不是非常通用的解决方案.os.path.isfile(file.name) - 看起来非常安全,但如果在某些创建模式下打开新文件我可能无效.file.fileno() == 0 - 这假设方法未实现,默认实现返回0,正常实现永远不会返回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>'
Run Code Online (Sandbox Code Playgroud)
(提示,就在我做的前一刻touch '<stdin>')
此外,在UNIX中,习惯上在打开临时文件后立即取消链接,因此它们不再存在于该名称中; 另一方面,即使现有文件在打开后也可以重命名,因此原始名称不存在.
如果要查看标准流是否重定向到文件,可以执行以下操作:
>>> import os
>>> import stat
>>> stat.S_ISREG(os.fstat(sys.stdout.fileno()).st_mode)
False
Run Code Online (Sandbox Code Playgroud)
S_ISREGTrue如果模式描述了普通文件,则返回(此处输出转到终端,因此它为False); 同样,你可以找出是否有任何文件被重定向到一个终端有isatty:
>>> os.isatty(sys.stdout.fileno())
True
Run Code Online (Sandbox Code Playgroud)