【问题标题】:python 3.x joblib simple save functionpython 3.x joblib 简单保存功能
【发布时间】:2019-12-31 12:27:38
【问题描述】:

我正在尝试创建一个简单的 joblib 函数,它将评估表达式并腌制结果,同时检查腌制文件是否存在。 但是当我将此函数放在其他文件中并在将文件的路径添加到 sys.path 后导入该函数时。我收到错误。

from pathlib import Path
import joblib as jl    
def saveobj(filename, expression_obj,ignore_file = False):
    fname = Path(filename)
    if fname.exists() and not ignore_file:
        obj = jl.load(filename)
    else:
        obj = eval(expression_obj)
        jl.dump(obj,fname,compress = True)        
    return obj

示例调用:

rf_clf = saveobj(file, "rnd_cv.fit(X_train, np.ravel(y_train))", ignore_file=True)

错误:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-11-02c2cae43c5d> in <module>
      1 file = Path("rf.pickle")
----> 2 rf_clf = saveobj(file, "rnd_cv.fit(X_train, np.ravel(y_train))", ignore_file=True)

~/Dropbox/myfnlib/util_funs.py in saveobj(filename, expression_obj, ignore_file)
     37         obj = jl.load(filename)
     38     else:
---> 39         obj = eval(expression_obj)
     40         jl.dump(obj,fname,compress = True)
     41     return obj

~/Dropbox/myfnlib/util_funs.py in <module>

NameError: name 'rnd_cv' is not defined

我猜,python 需要在本地评估函数,但由于该范围内不存在对象,因此会引发此错误。 有没有更好的方法来做到这一点。我需要重复执行此操作,这就是函数的原因。 非常感谢您的帮助。

【问题讨论】:

    标签: python pickle joblib


    【解决方案1】:

    您可以查看eval的文档:

    关于内置模块内置函数 eval 的帮助:

    eval(source, globals=None, locals=None, /)

    Evaluate the given source in the context of globals and locals.
    
    The source may be a string representing a Python expression
    or a code object as returned by compile().
    The globals must be a dictionary and locals can be any mapping,
    defaulting to the current globals and locals.
    If only globals is given, locals defaults to it.
    

    它有全局和局部变量的参数。因此,在您的情况下,您可以:

    from pathlib import Path
    import joblib as jl    
    def saveobj(filename, expression_obj,global,local,ignore_file = False):
        fname = Path(filename)
        if fname.exists() and not ignore_file:
            obj = jl.load(filename)
        else:
            obj = eval(expression_obj, global, local)
            jl.dump(obj,fname,compress = True)        
        return obj
    

    代码可以改成:

    rf_clf = saveobj(file, "rnd_cv.fit(X_train, np.ravel(y_train))", globals(), locals(), ignore_file=True)
    

    【讨论】:

      【解决方案2】:

      当我看到@youkaichao 的回答时,我正准备回答我自己的问题。非常感谢。 另一种给猫剥皮的方法:(尽管仅限于关键字参数)

      def saveobj(filename,func, ignore_file = False, **kwargs):
          fname = Path(filename)
          if fname.exists() and not ignore_file:
              obj = jl.load(filename)
          else:
              obj = func(**kwargs)
              jl.dump(obj,fname,compress = True)        
          return obj
      

      更改呼叫:

      file = Path("rf.pickle")
      rf_clf = saveobj(file, rnd_cv.fit, ignore_file=False, X=X_train, y= np.ravel(y_train))
      

      虽然,我还是很想知道,哪个更好。

      【讨论】:

      • 我认为我的更好。您必须根据func 传递任何附加参数。对于我来说,即使func 发生变化,对saveobj 的调用也不会改变。
      • @youkaichao 感谢您的投入,尽管我一直在寻找更微妙的答案。更具体地说,与简单的 **kwargs 调用相比,全局变量和局部变量将如何传播以及它们增加了什么样的内存和计算复杂度。顺便说一句,我也接受了你的回答
      • 不,我的答案不被接受:(你只能接受一个答案。
      • 无论你是否调用globals(),所有全局变量和局部变量都由python解释器维护,所以globals()locals()需要的成本可以忽略不计(只是传递一个引用)。跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 2015-04-13
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多