Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 子流程调用因web表单输入中的unicode数据而失败-可用于其他地方的相同输入_Python_Unicode_Cgi_Subprocess_Lighttpd - Fatal编程技术网

Python 子流程调用因web表单输入中的unicode数据而失败-可用于其他地方的相同输入

Python 子流程调用因web表单输入中的unicode数据而失败-可用于其他地方的相同输入,python,unicode,cgi,subprocess,lighttpd,Python,Unicode,Cgi,Subprocess,Lighttpd,我有一个库,其中包含一个函数,该函数根据多个regexp检查各种输入数据,以确保数据有效。对于CGI脚本从web表单(通过lighttpd)接收到的输入,以及从sqlite数据库读取的输入(该输入根据gammu smsd接收到的SMS依次放在那里),都会调用该函数 输入有时用英语,有时用印地语,即德夫纳加里语。应始终使用UTF-8对其进行编码。我一直在努力使用python的re和regex模块,在将字符类与Devnagari字符正确匹配时,这些模块似乎存在缺陷(您可以看到一个示例——在这种情况下

我有一个库,其中包含一个函数,该函数根据多个regexp检查各种输入数据,以确保数据有效。对于CGI脚本从web表单(通过lighttpd)接收到的输入,以及从sqlite数据库读取的输入(该输入根据gammu smsd接收到的SMS依次放在那里),都会调用该函数

输入有时用英语,有时用印地语,即德夫纳加里语。应始终使用UTF-8对其进行编码。我一直在努力使用python的re和regex模块,在将字符类与Devnagari字符正确匹配时,这些模块似乎存在缺陷(您可以看到一个示例——在这种情况下,使用regex而不是重新修复问题,但我也遇到了regex的问题)。命令行“grep”看起来更加可靠和准确。因此,我求助于使用子流程调用将必要的字符串通过管道传输到grep,如下所示:

def invalidfield(datarecord,msgtype):
  for fieldname in datarecord:
    if (msgtype,fieldname) in mainconf["MSG_FORMAT"]:
        try:
            check = subprocess.check_output("echo '" + datarecord[fieldname] + "' | grep -E '" + mainconf["MSG_FORMAT"][msgtype,fieldname] + "'",shell=True)
        except subprocess.CalledProcessError:
            return fieldname
return None
现在,让我们用以下字符串作为输入来尝试一下:
न्याज अहमद्
和下面的正则表达式进行检查:
^[[:alnum:][.]*[:alnum:][.[:alnum:][.]*$

奇怪的是,当从数据库中读取时,完全相同的输入会清除这个regexp(正如它应该的那样),并且函数会正确返回。但是,当通过webform输入相同的字符串时,subprocess.check_out将失败,并出现以下错误:

File "/usr/lib/python2.7/subprocess.py", line 537, in check_output
  process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
  errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1259, in _execute_child
  raise child_exception
TypeError: execv() arg 2 must contain only strings
我搞不懂发生了什么事。我已经用它修改了lighttpd.conf,至少应该确保lighttpd.conf使用utf-8字符集。我还使用了该模块,并对来自webform的输入运行chardet.detect。我知道:
{'confidence':1.0,'encoding':'ascii'}{'confidence':0.99,'encoding':'utf-8'}

根据这一点,我试着用unicode(datarecord[fieldname])替换上面的
datarecord[fieldname]
。编码('utf8'),并且第一次尝试用“ascii”编解码器解码datarecord[fieldname]。后者失败,通常出现“序号不在范围内”错误


这里出了什么问题?我就是搞不懂

在这种情况下,您希望避免使用
echo
;将输入直接写入
Popen()
对象的
stdin
管道

请确保您的环境设置为正确的语言环境,以便
grep
知道如何将输入解析为UTF-8:

env = dict(os.environ)
env['LC_ALL'] = 'en_US.UTF-8'
p = subprocess.Popen(['grep', '-E', mainconf["MSG_FORMAT"][msgtype,fieldname]], stdin=subprocess.PIPE, env=env)
p.communicate(datarecord[fieldname])
if p.returncode:
     return fieldname

为了补充Martijn Pieters的答案,他建议的解决方案在输入字符串为空的情况下将失败(与原始函数不同,grep将无法匹配空字符串,即使regexp允许它)。因此,原始功能的完整实现将是:

if (msgtype,fieldname) in mainconf["MSG_FORMAT"]:
        if not datarecord[fieldname]:
            if not regex.search(mainconf["MSG_FORMAT"][msgtype,fieldname],datarecord[fieldname],regex.UNICODE):
                return fieldname
        else:               
            curenv = os.environ
            curenv['LC_ALL']="en_US.UTF-8"
            check = subprocess.Popen(['grep','-E', mainconf["MSG_FORMAT"][msgtype,fieldname]], stdin=subprocess.PIPE, env=curenv, stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
            check.communicate (datarecord[fieldname]) 
            if check.returncode:
                return fieldname
return None

这就像
regex
匹配可以在空字符串上很好地工作。

打印repr(datarecord[fieldname])给你什么?它将是
datarecord[fieldname].encode('utf8')
(无需将unicode转换为unicode)。因为这是一个CGI脚本,我不得不要求它写出
str(repr(datarecord[fieldname]))
到文件中。我知道:'\xe0\xa4\xa8\xe0\xa5\x8d\xe0\xa4\xaf\xe0\xa4\xbe\xe0\xa4\x9c\xe0\xa4\x85\xe0\xa4\xb9\xe0\xa4\xae\xe0\xa4\xa6\xe0\xa5\x8d'并使用数据记录[fieldname]。编码('utf8')也不起作用……如果必须使用
grep-E
,为什么不将数据写入
grep
子流程的
stdin
管道,而不是使用
echo
shell=True
。对不起,我错了-这实际上不起作用。我的代码中有一个bug(我仍然在检查CalledProcessError,Popen没有提出这个问题)。当我重写代码时,我发现了两件事——首先是文件句柄有问题,之后grep一直无法匹配,即使它从命令行匹配。其他人似乎报告了Popen.communicate的编码问题(例如,请参阅,但对我来说,这个解决方案也没有什么好运气。您对unicode编码和Python的理解有多深?有帮助吗?您需要将编码与
grep
所期望的匹配,这可能是基于
LC
环境变量系列。我已经阅读了文档,但我承认我仍然对py中的unicode感到困惑。)我使用
reload(sys);sys.setdefaultencoding('utf-8'))
在程序开始时,以及来自uuu future\uuuuu导入unicode\u文字的
,以尝试强制统一编码。我在开始时遇到了许多问题,但大多数问题似乎已经解决。这是唯一剩下的问题。更奇怪的是,它可以处理来自sms数据库的数据,但不能处理来自CGI表单的数据。相信我,这是非常令人困惑和恼火的。:
setdefaultencoding()
应该永远都不需要;这只是表明您在某个地方以不应该的方式混合了字节和unicode。可能吧。我使用它来确保CGI脚本的输出始终正确编码(而不是在每个输出上手动强制使用utf8,因为它的大部分都在Devnagari中)。