特别库
只有一个“特别的”知识库,名叫 special。
特别知识库里装的是各种辅助性知识,以有趣的形式,确定陈述是否真实。
特别库里的知识项是 Python 函数,在程序运行中做些“特别”的事情。
这些“特别”的函数是:
- 函数 claim_goal
- 函数 check_command
- 函数 command
- 函数 general_command
函数 Claim_goal
函数 claim_goal 没有参数。
special.claim_goal()
它的行为方式,像是 Prolog 的 cut 操作。
一般有多个规则,用于尝试证明目标(结论)是否成立。规则应用的顺序,按其在 .krb 文件中的排列,逐一尝试。一个规则失败,就接着试下一个。规则全部失败,则目标失败。
示例
假设我要把数字 N 解释成“N 只狗”,就用到以下规则:
one_dog
use n_dogs(1, '1 dog')
n_dogs
use n_dogs($n, $phrase)
when
$phrase = "%d dogs" % $n
程序的逻辑有问题。当 n 等于 1 时,两个规则都要用到,但第二个规则不能正确适用。这时,函数 special.claim_goal() 可以解决这个问题:
one_dog
use n_dogs(1, '1 dog')
when
special.claim_goal()
n_dogs
use n_dogs($n, $phrase)
when
$phrase = "%d dogs" % $n
在 n 等于 1 时,special.claim_goal() 阻止适用第二个规则。
说明
规则 when 子句里调用函数 special.claim_goal() 时,其余的规则不再参与证明原目标。于是,如果 special.claim_goal() 引起回溯,目标立即失败,不再试用别的规则。
这种结束的方式,就像 if-then-else 结构中的“else”的作用。只有当规则 when 子句中的前提条件真实正确时,才能在其后使用 special.claim_goal()
你不必在其后适用的规则中,添加额外的前提条件,去确保它们没有发生。
如果上例中没有函数 special.claim_goal(),你只好这样写:
one_dog
use n_dogs(1, '1 dog')
n_dogs
use n_dogs($n, $phrase)
when
check $n != 1
$phrase = "%d dogs" % $n
这个简单的例子,很容易在第二个规则中,加入命令 check。不过,一般地说,检查以前出现的条件是很困难的,尤其如果涉及到多个规则,并且它们有各自的条件。
运行命令
其余三个函数,在你的 Pyke 程序运行时,以命令运行处理其他程序。这三个函数执行后,有不同的输出结果。
这三个函数,都使用 Python 标准库函数 subprocess.Popen。
这三个函数,都有以下三个参数,传递给 subprocess.Popen:
- 必须的参数 $command。
- 它是个元组,告诉程序按照参数的值运行,例如 (ls, '-l')。
- 可选的参数 $cwd。
- 指定程序当前运行的硬盘目录。
- 如果未设值,或设为 None,则当前工作目录保持不变。
- 可选的参数 $stdin。
- 是个字符串,指明程序的标准输入。
- 如果程序的输入有多行,$stdin 必须包括嵌入的新行,如:“line 1/nline 2/n”。
- 如果未设值,或设为 None,则该程序没有标准输入。
- 是个字符串,指明程序的标准输入。
如果发生回溯,这些函数全部失败。
函数 Check_command
special.check_command($command [, $cwd [, $stdin]])
如果 $command 程序运行返回 0,它适用成功;返回其他值,失败。程序向 stdout 和 stderr 的输出,无意义。
>>> from pyke import knowledge_engine
>>> engine = knowledge_engine.engine()
>>> engine.prove_1_goal('special.check_command((true))')
({}, None)
>>> engine.prove_1_goal('special.check_command((false))')
Traceback (most recent call last):
...
CanNotProve: Can not prove special.check_command((false))
函数 Command
special.command($stdout, $command [, $cwd [, $stdin]])
它输出到 stdout。$command 程序向 stderr 的输出,无意义。
$stdout 是包含多行内容的元组,行尾的换行符都删除了。
如果程序返回值不是 0,则引发意外 subprocess.CalledProcessError。
>>> from __future__ import with_statement
>>> from pyke import pattern, contexts
>>> def run_command(entity, command, cwd=None, stdin=None):
... with engine.prove_goal(
... 'special.%s($output, $command, $cwd, $stdin)' % entity,
... command=command,
... cwd=cwd,
... stdin=stdin) /
... as gen:
... for vars, no_plan in gen:
... print vars['output']
>>> run_command('command', ('echo', 'hi', 'mom'))
('hi mom',)
>>> run_command('command', ('ls',)) # doctest: +NORMALIZE_WHITESPACE
('fact_bases.txt', 'index.txt', 'links', 'question_bases.txt',
'rule_bases.txt', 'special.txt')
>>> run_command('command', ('ls', '-l', 'links')) # doctest: +ELLIPSIS
('-rw-r--r-- 1 ... links',)
>>> run_command('command', ('tail', '-n', '5', 'template.txt', '-'),
... '..', # cwd (doc/source)
... 'stdin: line 1/nstdin: line 2/nstdin: line 3/n')
... # doctest: +NORMALIZE_WHITESPACE
('==> template.txt <==',
' } catch(err) {}',
' ',
'',
'',
'',
'',
'==> standard input <==',
'stdin: line 1',
'stdin: line 2',
'stdin: line 3')
>>> run_command('command', ('false',))
Traceback (most recent call last):
...
CalledProcessError: Command 'false' returned non-zero exit status 1
special.general_command($output, $command [, $cwd [, $stdin]])
$command 程序给你全部输出的最一般的形式。
$output 是有三个成员的元组:(exit_status, stdout, stderr)。stdout 和 stderr 都是有换行符的字符串。
>>> run_command('general_command', ('echo', 'hi', 'mom'))
(0, 'hi mom/n', '')
>>> run_command('general_command', ('cat', 'foobar'))
(1, '', 'cat: foobar: No such file or directory/n')
>>> run_command('general_command', ('tail', '-n', '5', '../../r2w.ini', 'foobar'))
... # doctest: +NORMALIZE_WHITESPACE
(1,
"==> ../../r2w.ini <==/ntarget_directory = 'html'/nmacros =
''/n/n[uservalues]/nversion = '0.2'/n",
"tail: cannot open `foobar' for reading: No such file or directory/n")
本文介绍了Python中的一个特殊知识库,它包含各种有趣的函数,用于在程序运行时执行辅助任务。主要介绍了claim_goal、check_command、command和general_command四个函数的功能、用法和应用场景。
1013

被折叠的 条评论
为什么被折叠?



