5

当我传递程序中的选项(计算生物学实验)时,我通常通过 .py 文件传递​​它们。
所以我有这个 .py 文件,内容如下:

starting_length=9
starting_cell_size=1000
LengthofExperiments=5000000

然后我执行文件并获取数据。由于该程序都在我的机器上,没有其他人可以访问它,因此它以一种微不足道的方式是安全的。
我也可以很容易地写一个类似的文件:

def writeoptions(directory):
    options=""
    options+="starting_length=%s%s"%(starting_length,os.linesep)
    options+="starting_cell_size=%s%s"%(starting_cell_size,os.linesep)
    options+="LengthofExperiments=%s%s"%(LengthofExperiments,os.linesep)
...
    open("%s%soptions.py"%(directory,os.sep),'w').write(options)

我想将函数作为参数之一传递:

starting_length=9
starting_cell_size=1000
LengthofExperiments=5000000

def pippo(a,b):
    return a+b
functionoperator=pippo

当然,在实际实验中,函数 pippo 会复杂得多。并且因实验而异。

但我无法做的是自动编写函数。简而言之,如果其中一个选项是函数,我不知道如何概括 writeoptions 函数以继续编写选项。我当然可以复制原始文件,但这不优雅、效率低下(因为它包含许多未使用的额外选项),并且通常无法解决问题。

你如何让python写下一个函数的代码,因为它写下一个变量的值?

4

5 回答 5

15
vinko@mithril$ 更多 a.py

定义 foo(a):
  打印一个

vinko@mithril$ 更多 b.py

导入一个
进口检验

a.foo(89)
打印检查.getsource(a.foo)

vinko@mithril$ python b.py
89
定义 foo(a):
  打印一个

于 2008-12-30T11:18:39.257 回答
2

您还可以考虑其他一些数据持久性的方法。在我自己的(天文学)研究中,我一直在试验两种不同的存储脚本以实现可重复性的方法。第一种是将它们专门放在 subversion 存储库中,然后让作业提交脚本自动提交它们。例如,如果您只想在 bash 中执行此操作:

alias run_py='svn ci -m "Commit before running"; python2.5 $*'

在脚本内部,输出以该文件的当前颠覆修订号为前缀,您将记录每个运行的脚本以及输入是什么。您可以根据需要将其从颠覆中撤出。

另一种功能少得多的跟踪函数输入的方法可能是通过LodgeIt 之类的东西,它是一个接受 XML-RPC 输入并带有 Python 绑定的 pastebin。(它可以在本地安装,并且支持回复和更新现有的粘贴。)

但是,如果您正在寻找包含的代码量相对较少,Vinko 使用检查的解决方案应该可以很好地工作。Doug Hellman在他的Python Module of the Week系列中介绍了该inspect模块。您可以创建一个装饰器来检查每个选项和参数,然后根据需要将其打印出来(我将使用它来获取参数的名称。)inspect.getargspec

import inspect
from functools import wraps

def option_printer(func):
    @wraps(func)
    def run_func(*args, **kwargs):
        for name, arg in zip(inspect.getargspec(func)[0], args) \
                       + sorted(kwargs.items()):
            if isinstance(arg, types.FunctionType): 
                print "Function argument '%s' named '%s':\n" % (name, func.func_name)
                print inspect.getsource(func)
            else:
                print "%s: %s" % (name, arg)
        return func(*args, **kwargs)
    return run_func

这可能会更优雅一点,但在我的测试中,它适用于简单的参数和变量集。此外,它可能对 lambdas 有一些问题。

于 2008-12-30T14:12:54.320 回答
0

你是在问这个吗?

def writeoptions(directory):
    options=""
    options+="starting_length=%s%s"%(starting_length,os.linesep)
    options+="starting_cell_size=%s%s"%(starting_cell_size,os.linesep)
    options+="LengthofExperiments=%s%s"%(LengthofExperiments,os.linesep)
    options+="def pippo(a,b):%s" % ( os.linesep, )
    options+="    '''Some version of pippo'''%s" % ( os.linesep, )
    options+="    return 2*a+b%s" % ( os.linesep, )
    open("%s%soptions.py"%(directory,os.sep),'w').write(options)

或者是其他东西?

于 2008-12-30T11:21:05.697 回答
0

虽然可以按照您的要求去做(如 Vinko 所示),但我想说共享代码更干净。将pippo和他的伙伴放在两个程序都可以访问的子模块中。

于 2008-12-30T11:24:44.237 回答
0

与其深入研究反汇编程序和字节码(例如inspect),不如将生成的 Python 源代码保存在模块(file.py)中,然后再导入它?

我建议研究一种更标准的方式来处理您所谓的options。例如,您可以使用JSON模块并保存或恢复您的数据。或者查看marshalpickle模块。

于 2008-12-30T11:25:27.793 回答