【问题标题】: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

一旦将无效的文件句柄用于任何事情,就会出现问题。有没有办法在引发异常之前检查文件句柄是否有效?

【问题讨论】:

    标签: exception-handling io raku


    【解决方案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()?

    还有:

    一个潜在的解决方法目前是另一个错误?

    在讨论"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::HandleIO::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 的代码也有效。问题是每个人都在编写代码时期望它是失败而不是异常。那么为什么不这样做呢?
    猜你喜欢
    • 2011-03-24
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多