使用Python调用Sicstus的OS系统调用无限挂起

1 投票
1 回答
585 浏览
提问于 2025-04-18 08:09

我正在尝试写一个证明检查应用程序,这个程序可以从网站上接收用户提交的证明,然后把它发送给一个Prolog脚本来检查证明的有效性。

我使用的是Django、Python 2.7和Sicstus。在我的服务器的“view.py”文件中,我调用了一个名为“checkProof.py”的Python脚本,把用户提交的证明的原始文本传递给它。在这个文件里,我有一个这样的函数:

def checkProof(pFile, fFile):
    p = subprocess.Popen(['/bin/bash', '-i', '-c', 'sicstus -l ProofServer/server/proofChecker.pl -- %s %s' % (pFile, fFile)],
        stdout=subprocess.PIPE)
    p.communicate() # Hangs here.

proofChecker.pl接收一个修改过的证明版本(pFile),对其进行分析,并把反馈输出到一个反馈文件(fFile)中。这个Python脚本会循环,直到生成反馈文件,然后把这个反馈返回给服务器的其他部分。

第一次调用这个函数时,一切正常,我得到了预期的输出。可是第二次调用这个函数时,程序在“p.communicate()”这一步卡住了,无法继续。

这就意味着,目前这个应用程序在服务器重启之间只能检查一个证明。其实服务器应该能够在重启之间检查无限数量的证明。

有没有人知道为什么会这样?如果需要,我很乐意提供更多信息。

更新

根据下面的建议,我尝试了三种不同的调用方式,想找出问题出在哪里。第一种是我已经在做的,调用Sicstus来处理我的真实证明检查代码。第二种是调用一个非常简单的Prolog脚本,它只输出一些固定的内容。第三种是一个简单的Python脚本,效果也是一样:

def checkProof(pFile, fFile):
  cmd1 = 'sicstus -l ProofServer/server/proofChecker.pl -- %s %s' % (pFile, fFile)
  cmd2 = 'sicstus -l ProofServer/server/tempFeedback.pl -- %s %s' % (pFile, fFile)
  cmd3 = 'python ProofServer/server/tempFeedback.py %s %s' % (pFile, fFile)
  p = subprocess.Popen(['/bin/bash', '-i', '-c', cmd3],
      stdout=subprocess.PIPE)
  p.communicate() # Hangs here.

在这三种情况下,应用程序在第二次尝试调用时依然卡住。这说明问题不在于调用Sicstus,而是我调用程序的方式有问题。这让我稍微放心了一点,但我还是不确定自己哪里做错了。

1 个回答

1

我最终解决了这个问题。

我觉得问题出在加上了 -i(交互式)这个标志,这让 bash 期待输入,但当没有输入时,它在第二次调用时就挂起了进程。这就是我在尝试用更简单的方式复制这个过程时发生的事情。

我去掉了 -i 这个标志,结果发现现在出现了错误“/bin/bash: sicstus: 找不到命令”,尽管 sicstus 在我服务器的 PATH 中,我通过 SSH 直接进入服务器时可以正常调用它。我通过指定完整路径解决了这个问题。现在我可以在服务器重启之间无限次检查证明,这太好了。我的代码现在是:

def checkProof(pFile, fFile):
  cmd = '/usr/local/sicstus4.2.3/bin/sicstus -l ProofServer/server/proofChecker.pl -- %s %s' % (pFile, fFile)
  p = subprocess.Popen(['/bin/bash', '-c', cmd])
  p.communicate()

撰写回答