从 memcached 加载 json_encoded PHP 数组时出现 Unicode 错误

Unicode error when loading a json_encoded PHP array from memcached

我需要使用 python 将 PHP 关联数组传输到进一步处理。 python 代码但是使用 pylibmc 无法从 memcached 加载字符串,抛出此错误:

UnicodeDecodeError: 'utf8' codec can't decode byte 0xe0 in position 32: invalid continuation byte

我写了一个小测试器。 PHP 创建 memcached 数据的代码:

<?php
$mc = new Memcached();
$mc->addServer('localhost', 11211);

$data = array();

for ( $i = 0; $i < 100; $i++) {
  $index = "ti" . $i;
  $data += [$index => "test string $i"];
}

$mc->delete('test');
$mc->add('test', json_encode($data), 60);

$reverse = $mc->get('test');
echo "$reverse\n";  // prints {"ti0":"test string 0" ...... "ti99":"test string 99"} as expected

$reverse_array = json_decode($reverse, true);

echo $reverse_array['ti10'] . "\n";
//prints 'test string 10' as expected
?>

所以这可以很好地从 PHP 写入 memcached 并读回它。

在 python 方面,这是我用来读取它的代码:

#!/usr/bin/python
import pylibmc
import json

mc = pylibmc.Client(["127.0.0.1"], binary=True, behaviors={"cas": True, "tcp_nodelay": True,"ketama": True})

temp = json.loads(mc.get("test"))

当运行 python 代码时,这是我得到的输出:

Traceback (most recent call last):
  File "./mctest.py", line 7, in <module>
    temp = json.loads(mc.get("test")))
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe0 in position 32: invalid continuation byte

如果我在 PHP 中创建一个非关联数组并通过 memcached 共享它,一切正常。

我试过的另外两个选项:

添加 utf8_encode 以确保编码正确:

$mc->add('test', utf8_encode(json_encode($data)), 60);

将 JSON_UNESCAPED_UNICODE 添加到 json_encode 函数:

$mc->add('test', json_encode($data, JSON_UNESCAPED_UNICODE), 60);

两者在 python 一方产生相同的结果。

有点不知所措 - 欢迎任何想法!

在尝试确定通过 pymemcache 从 memcached 检索到的结果字符串的编码时,我发现该字符串看起来不像任何已知编码,我使用 chardet 和 cchardet 确认了这一点。

在 PHP 端进一步挖掘后,我发现 PHP memcached 模块通过压缩数据篡改了它保存到 memcached 的字符串!

解决方案是将此行添加到 /etc/php/7.2/cli/conf.d/25-memcached.ini 文件中:

memcached.compression_threshold=9999999999

现在数据进入python,这是它应该的!