0

我正在使用 Python2.7,SPARC ASP 求解器,并且正在从 Ubuntu14.04 命令行运行我的代码。

我正在尝试在我的 Python 代码和我的 ASP(答案集编程)代码之间建立双向通信。为此,我从 python 向 ASP 发送查询,将 ASP 响应放入 fifo 管道,在 python 代码中,fifo 的内容被读入字符串,然后将该字符串写入文本文件(这是这样的我可以检查文本文件,看看我是否得到了我期望的输出)。然而,出现了两个问题:文本文件中只出现了部分预期响应,而不是全部,虽然我的 python 代码处于无限循环中,但它似乎只运行一次。出了什么问题?

不幸的是,尽管进行了数天的研究并就堆栈溢出提出了一些较小的问题,并且尽管本网站上的好人提供了一些非常有用的答案,但我仍然无处可去,我不确定我的代码中的问题出在哪里。所以我将发布我所有的代码,希望有人可以帮助我一劳永逸地解决这个问题。

我的python代码:

import sys
import os

while True:
    # communicate with ASP code
    try:
        sys.stdout.write('moveForward(turtlebot)\n')
    except KeyboardInterrupt:
        sys.stdout.write('moveForward(turtlebot)\n')
        sys.exit()

    # read back the output of the ASP code - should be '?- yes'
    try:
        fifo = os.open('fifo', os.O_RDONLY)
        string = os.read(fifo, 7)
        os.close(fifo)
    except KeyboardInterrupt:
        fifo = os.open('fifo', os.O_RDONLY)
        string = os.read(fifo, 7)
        os.close(fifo)
        sys.exit()  

    # write the latest output to the text file
    try:
        myfile = open("afile.txt", "w")
        myfile.write(string)
        myfile.close()
    except KeyboardInterrupt:
        myfile = open("afile.txt", "w")
        myfile.write(string)
        myfile.close()
        sys.exit()

我的 ASP 代码:

sorts
#robot = {turtlebot}.

predicates
moveForward(#robot).

rules
moveForward(turtlebot).

我如何从命令行运行我的代码:

mkfifo fifo
python test.py | java -jar sparc.jar aspfile.sp > fifo

发生了什么:
运行我的代码后,我检查afile.txt了写了什么。它总是公正?-的,没有“是”。我还可以看出我的 python 代码只运行一次,因为当我追加到文本文件而不是写入时,每次运行我的代码时只添加一行。ASP 求解器的输出应该?- yes.

我怀疑问题出在 ASP 代码中,因为如果在命令行中我键入> sparc.out而不是> fifo(这样输出直接放入文本文件而无需先经过 fifo),则文本文件包含几十个重复的?- yes,这是我所期望的。

我需要弄清楚如何使用 fifo 而不是仅仅将输出写入文本文件,因为对于我的代码所针对的应用程序而言,不断地读取/写入文本文件太慢了(为turtlebot 创建一个行动计划;当我在机器人上测试了文本文件版本,它不断停止和启动,因为它每次从文本文件中读取时都会暂停)。

我知道将所有代码转储到帖子中并说“为我修复它!”并不是很好的形式,但我无能为力。如果有人可以帮助我进行双向沟通,我将非常感激。

4

1 回答 1

1

对我来说似乎是一个缓冲问题。使用write并不意味着其他进程已完全收到您的消息。这只是意味着它们已被复制到您的内部写入缓冲区。这个缓冲区的大小通常为 4k,如果它没有被完全填满,则不会将任何内容发送到另一端。同样,当您read不能期望 7 个字节立即可用时,因为另一端可能没有发送足够的数据。SPARC 很可能只打印'?- '您立即收到的 ,然后等待您尚未发送的输入。您可以强制发送带有flush. 您可能还需要closestdout (隐式调用flush用于发送非空写缓冲区),因为 SPARC 可能会在开始计算之前等待 EOF。

发送输入后尝试使用sys.stdout.close(which calls ),并在循环中使用,直到收到返回值,因为目前可用的字节可能少于 7 个。flushread0

这里也是标准输出缓冲的一个很好的概述:http ://www.pixelbeat.org/programming/stdio_buffering/

于 2017-04-28T05:13:19.667 回答