【问题标题】:Why is YAML throwing float ArgumentErrors on strings?为什么 YAML 会在字符串上抛出浮点 ArgumentErrors?
【发布时间】:2013-04-20 23:43:33
【问题描述】:

我在触发“ArgumentError”异常的复杂哈希中有一些嵌套字符串。处理此问题的最佳实践方法是什么?

require 'yaml'
{
    a: 'hello',
    b: [{f:'hello',g:Hash.new,i:{a:'hello'}}],
    c: {e:"+."}
}.to_yaml #=> `Float': invalid value for Float(): "+" (ArgumentError) 

完整的错误转储:

/Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/scalar_scanner.rb:99:in `Float': invalid value for Float(): "+" (ArgumentError)
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/scalar_scanner.rb:99:in `tokenize'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:272:in `visit_String'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:324:in `block in visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `each'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:324:in `block in visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `each'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:322:in `visit_Hash'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:92:in `push'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych.rb:244:in `dump'
    from /Users/XXX/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/core_ext.rb:14:in `psych_to_yaml'

【问题讨论】:

  • 使用 ruby​​ 2.0 无法重现错误,您使用的是什么版本?
  • ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin12.2.1]
  • 这很奇怪。 1.9.* 和 2.0 支持此语法。我知道由于哈希语法,这在 1.8.7 中不起作用。
  • 好吧,我首先意识到了这个错误,因为我的 ubuntu (ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]) 服务器把它扔给了我。然后我在我的 OSX 机器上本地测试它,同样的问题。
  • 1.9.3p125 对我来说效果很好,但 2.0.0p0 出现同样的错误。

标签: ruby string yaml psych


【解决方案1】:

这似乎是捆绑心理中的一个错误。在第 99 行修补 ~/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/psych/scalar_scanner.rb 来自:

Float(string.gsub(/[,_]|\.$/, ''))

到:

Float(string.gsub(/[,_]|\.$/, '')) rescue ArgumentError

解决了这个问题。这基本上就是 psych gem 以及 Ruby 1.9 捆绑版本中的内容。

如果您不想修补 Ruby,则使用 psych-1.3.4 gem 是另一种选择;一定要require 'psych'而不是'yaml'

gem 'psych', '=1.3.4'
require 'psych'
{a: 'hello', b: [{f:'hello',g:Hash.new,i:{a:'hello'}}], c: {e:"0+."}}.to_yaml
# => "---\n:a: hello\n:b:\n- :f: hello\n  :g: {}\n  :i:\n    :a: hello\n:c:\n  :e: 0+.\n"

【讨论】:

  • 这是一个错字。应该是require 'psych'。 ;-)
  • 哈,是的,我就是这个意思。但也同样的错误。我只是复制并粘贴了您的答案,而不是更正类型:P
  • 如果您遇到 same 错误,我怀疑您处于与 required 'yaml' 相同的 irb 会话中。跨度>
  • 不确定,Rubymine 是我的 IDE。所以它应该重新加载?它对你有用吗?
  • 实际上,对不起——我不知道为什么,但现在心理宝石也对我不起作用。我不知道我之前做了什么,当它似乎有效时。 to_yaml 仍在调用捆绑的那个。该补丁肯定仍然有效。
【解决方案2】:

这可以用一个更简单的例子来重现:

"+.".to_yaml

这似乎是与 ruby​​ 2.0.0 捆绑在一起的 psych 版本中的一个错误(我敢肯定还有其他版本):

  when FLOAT
    if string == '.'
      @string_cache[string] = true
      string
    else
      Float(string.gsub(/[,_]|\.$/, ''))
    end

问题是那个“+”。看起来像 +.5 这样的有效浮点数。

这在 Ruby 2.2.1(或者可能是更早的版本)中得到了修复,它专门检查可能存在前导符号(+ 或 -)的情况:

  when FLOAT
    if string =~ /\A[-+]?\.\Z/
      @string_cache[string] = true
      string
    else
      Float(string.gsub(/[,_]|\.$/, ''))
    end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 2022-07-21
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 1970-01-01
    相关资源
    最近更新 更多