处理无效的文件句柄(可能还有其他无效对象)
Posted
技术标签:
【中文标题】处理无效的文件句柄(可能还有其他无效对象)【英文标题】:Dealing with invalid filehandles (and maybe other invalid objects too) 【发布时间】:2019-06-27 07:58:12 【问题描述】:正如 Tom Browder 在 this issue 中指出的那样,如果命令行中提到的任何文件不存在,$*ARGFILES
dynamic variable 可能包含无效的文件句柄。
for $*ARGFILES.handles -> $fh
say $fh;
将失败并出现X::AdHoc
异常(这可能也应该改进):
Failed to open file /home/jmerelo/Code/perl6/my-perl6-examples/args/no-file: No such file or directory
一旦将无效的文件句柄用于任何事情,就会出现问题。有没有办法在引发异常之前检查文件句柄是否有效?
【问题讨论】:
【参考方案1】:您可以通过检查真实性或定义性没有 Failure
抛出来检查某事物是否为Failure
:
for $*ARGFILES.handles -> $fh
say $fh if $fh; # check truthiness
.say with $fh; # check definedness + topicalization
如果你还想扔掉Failure
所包含的Exception
,那么你可以直接.throw
它。
【讨论】:
还是同样的问题,在if $fh
级别抛出。第二个更奇怪,因为它说“错误的文件描述符”。
嗨@jjmerelo 和丽兹。在.handles
中抛出异常。它没有达到-> $fh
绑定的程度,更不用说进入块并执行if
语句。我希望这只是IO::CatHandle
中某个地方的调整,以返回Failure
而不是抛出。但即使这是固定的,请参阅我对 Zoffix 提出的解决方案的回答,这很奇怪 A)他们建议了它(为什么不只是 for
循环?)和 B)它有一个奇怪的错误。
问题是.handles
迭代器调用.next-handle
其中unconditionally throws the Failure。【参考方案2】:
TL;DR我以为 Liz 搞定了,但似乎有一个错误,或者可能是呃。
一个错误?
看起来每当IO::CatHandle
class's .handles
method 到达一个按权利应该产生Failure
的句柄(延迟任何异常抛出)时,它会立即抛出一个异常(如果它只是被延迟或者可能会工作的那个异常东西坏了)。
这似乎是错误的或非常错误的。
呃
见the exchange between Zoffix and Brad Gilbert and Zoffix's answer问题How should I handle Perl 6 $*ARGFILES that can't be read by lines()?
还有:
https://github.com/rakudo/rakudo/issues/1313
https://github.com/rakudo/rakudo/search?q=argfiles&type=Issues
https://github.com/rakudo/rakudo/search?q=cathandle&type=Issues
一个潜在的解决方法目前是另一个错误?
在讨论"Implement handler for failed open on IO::CatHandle"
Zoffix++ 时,使用此代码作为解决方案关闭它:
.say for ($*ARGFILES but role
method next-handle
loop try return self.IO::CatHandle::next-handle
)
我看到 tbrowder 已将此问题作为相关问题的一部分重新打开,这是该 SO 要说的:
如果这可行,它至少是文档中
$*ARGFILES
var 的可用示例。
但是当我在6.d
中运行它(并看到6.c
的类似结果)时,无论输入是否有效,我都会得到:
say not yet implemented
(如果我 .put
或其他类似)。
这很疯狂,表明一些大胆的事情正在搞砸。
我已在 rt 和 gh/rakudo 问题中搜索“尚未实施”,但没有找到相关匹配项。
另一种解决方法?
Zoffix 显然打算将他们的代码作为永久解决方案,而不仅仅是一种变通方法。但不幸的是,它现在似乎根本不起作用。
目前为止我想出的最好的:
try $*ARGFILES andthen say $_ # $_ is a defined ArgFiles instance
orelse say $!; # $! is an error encountered inside the `try`
也许这是一个黑白的作品,它要么全部有效,要么没有一个解决方案。 (虽然我不相信它就是这样。)
文档对$*ARGFILES
的评价
$*ARGFILES
说它是一个实例
IO::ArgFiles
被记录为一个类
出于向后兼容性的原因而存在并且不提供任何方法。
和
所有功能都继承自
IO::CatHandle
副标题为
使用多个 IO 句柄,就好像它们是一个句柄一样
并将 doc'd 作为 is
的类
IO::Handle
副标题为
打开的文件或流
并作为一个不从任何其他类继承的类(因此默认为从Any
继承)或做任何角色。
因此,$*ARGFILES
是(在功能上与)IO::CatHandle
对象(功能的超集)IO::Handle
对象,具体来说:
IO::CatHandle
类提供了一种创建IO::Handle
的方法,该IO::Handle
可以无缝地从多个IO::Handle
和IO::Pipe
源收集输入。IO::Handle
的所有方法都已实现,虽然尝试使用 write 方法将(当前)抛出异常,但IO::CatHandle
可用于任何可以使用只读IO::Handle
的地方。
探索the code for IO::CatHandle
(以后填写?)
【讨论】:
$*ARGFILES 没问题,它是 $*ARGFILES.handles 引发错误的那个。但在这种情况下,尝试可能是一个好方法。 谢谢。我两次严重偏离轨道(还有另一个与此无关的已删除答案,我可能永远不会透露。:))。 Anyhoo,答案重写。你接受这个答案对我来说还没有意义。您确定我的解决方法对您或 Tom 有效吗? 您不必透露它。如果一个人有足够的声望点,他们仍然可以阅读它。.next-handle
throws the Failure as soon as it sees it
@BradGilbert Thx 了解有关揭示的信息。是的,您链接的代码显然是问题所在。你和 Zoffix 已经根据我在 bdfoy 发布的 SO 上链接的交流讨论了它,对吧? (我正在尝试正确理解 Zoffix 的观点与您的观点之间的优缺点。)我在答案的 Ugh 部分中包含的链接中列出的错误是否已经充分涵盖了问题,或者你认为我们需要发布另一个问题吗?与此同时,您是否对 A potential workaround is current is another bug? 部分中奇怪的 not yet implemented
消息有任何线索?
据我所知,删除 .throw
不会导致任何以前工作的代码突然失败。它应该使 Zoffix 的上述代码有效,它应该使 lizmat 的代码也有效。问题是每个人都在编写代码时期望它是失败而不是异常。那么为什么不这样做呢?以上是关于处理无效的文件句柄(可能还有其他无效对象)的主要内容,如果未能解决你的问题,请参考以下文章
linux删除文件后空间无法释放?lsof没有结果。重启无效。请问各位高手还有别的办法吗?