【问题标题】:Accessing python nltk with php fails使用 php 访问 python nltk 失败
【发布时间】:2015-12-06 03:08:07
【问题描述】:

我试图从我的 php 文件中调用一个包含句子/单词标记器的 python 文件,如下所示:

$output = shell_exec('python tokenizer.py $sentence')

我试过单个exec,python 和 tokenizer.py 的完整路径,用双引号括住 $sentence。但从逻辑上讲,这应该不是问题,因为在 python 的开头调用print(1),python 代码在实际使用任何 nltk 包之前使得$output 等于'1'。所以我得出的结论是,这里的问题是 nltk 本身,比如模块的路径不正确或什么的......

但是,使用与上面相同的命令从 shell 调用 python 会得到完全标记化的输出! 总结:当从 php 调用 python 时看起来像神奇地“关闭”nltk,而从 shell 执行时它完全可以工作。

这是我正在使用的python代码的一部分:

import sys
import nltk
from nltk.tokenize import sent_tokenize

sample_text2 = sys.argv[1]
gust = sent_tokenize(sample_text2)
#print(1) here doesn't work, but everywhere above (before calling sent_tokenize) it does.

服务器在 CentOS (Linux) 上运行,我通过 SSH 访问它。

明显的问题:我在 PHP 上做错了什么?还是一般?还有其他选择吗?

编辑 从 dvhh 的答案及其 cmets 中可以看出,这种情况的发生是因为服务器上安装了两个版本(2.6 和 2.7),而 www 用户可以通过控制台访问 2.6,默认版本是 2.7。解决方案是将两种情况下的默认 python 更改为 2.7,并将 nltk 模块放入依赖文件夹之一。 (或者使用 sys.path.append 附加依赖目录)

【问题讨论】:

  • 最明显的就是到处使用python。但是当你说不工作时,你看到错误了吗?
  • 不,即使我设置了 ini_set('display_errors' ,1),什么也没有。我想到处都用python,但是整个app都是用php写的,好像工作了两个星期。
  • 你在使用 virtualenv 吗?
  • 差不多。 shell_exec('python tokenizer.py ' . escapeshellarg($sentence));
  • 好的,只是为了回答你关于引号和正确转义的参数之间的区别的问题:单独的引号不会让你从“句子”中拯救你:foo"; rm -r /; echo "bar(不要尝试,顺便说一句)。

标签: php shell python-2.7 nltk


【解决方案1】:

您的 php 脚本由www 用户执行。

    1234563 t 设置了 PATH 环境变量。
    解决方案在您的 shell_exec 调用中指定您的 python 解释器的完整路径(还可以指定脚本的完整路径)在它)
  • nltk 库的安装路径如何,您可以通过在www 用户运行python 时查看sys.path 来检查python 解释器是否正确查找它.
    诊断:使用shell_exec 调用运行python 脚本来打印sys.path解决方案:将库路径附加到 Python 脚本中的 sys.path import nltk 之前

考虑到问题中提供的信息,这些将是最明显的解决方案。

更新:
由于安装了 2 个版本的 python(没有安装库),建议指定所需解释器的路径。第一个解决方案有助于纠正问题。 在类似 unix 的系统中,我建议使用 which python 命令来确定默认 python 解释器的路径。

【讨论】:

  • 跑了一下,我想我可以看出问题出在哪里了。当我修复它时会接受,谢谢!
  • 如果解决方案不在我提到的范围内,请随时发布您自己的答案/解决方案,或者您可以发表评论,我会修改答案以供将来参考
  • 是的,问题是安装了两个版本,2.6 和 2.7。这是这两种解决方案的组合,可能对我有所帮助。必须手动设置路径。
  • 澄清:python --version 返回 2.7.6,您建议的诊断返回所有适用于 python 2.6 的路径。
  • 感谢您的澄清,请在您的问题中添加信息以供将来参考
【解决方案2】:

选项 1

在 localhost 上设置一个简单的 python httpserver 监听。 This old answer 可能会有所帮助,但那里有很多方法。优点是每次需要执行 ntlk 的东西时你都不需要启动 python 解释器的开销,而且你不必担心 shell 脚本的执行、权限等。缺点是一些额外的工作和一个开销很小。

选项 2 使用任务队列。不管怎么说,从面向 Web 的 PHP 脚本执行命令都是不安全的。如果你已经在使用 RabbitMQ 或类似的东西,你可以在这里使用它。或者,如果您使用的是 redis,您可以使用 lpush、rpop 方法使 redis 表现得像一个队列。缺点:结果不是立即可用的。

选项 3

您的 php 脚本将数据输入到表中并设置您的 python 脚本以作为 cron 作业运行以每分钟检查一次表的另一种策略。缺点:结果不是立即可用的。

选项 4

您当前的选择,但如果选择此选项,请确保您已通过 @lafor 正确转义数据 @dvhh 的答案应该有效。

【讨论】:

    【解决方案3】:

    就我而言,这不是 python 版本的问题,而是 nltk_data 文件夹的问题(我很快发现)。一开始我以为是权限问题,所以我把权限改成了777,但是还是不行。

    我必须复制文件夹。

    首先,您必须找到安装 nltk 文件夹的位置。您可以通过在 bash 中运行 python3 命令找到它,然后输入以下行:

    import nltk
    
    nltk.download('punkt')
    nltk.download('averaged_perceptron_tagger')
    

    它会说:

    [nltk_data] Downloading package punkt to /root/nltk_data...
    [nltk_data]   Package punkt is already up-to-date!
    

    现在你知道你已经安装了它,例如在 /root 文件夹中(我在那里)。

    然后放入你的python脚本,由php调用:

    import nltk
    print(nltk.data.path)
    

    它将输出如下内容:(请注意,如果您从 php 脚本运行它或从命令行调用它,则文件夹是另一个文件夹)

    ['/var/www/nltk_data', '/usr/nltk_data', '/usr/share/nltk_data', '/usr/lib/nltk_data', '/usr/share/nltk_data', '/usr/local/share/nltk_data', '/usr/lib/nltk_data', '/usr/local/lib/nltk_data']
    

    现在只需将您的原始文件夹复制到上述任何文件夹即可。我做到了:

    cp /root/nltk_data /var/www/nltk_data -r
    

    瞧。现在可以了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-26
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      • 2014-12-28
      • 1970-01-01
      • 2012-10-26
      • 1970-01-01
      相关资源
      最近更新 更多