使用 Plack 和 Middlewares 时将默认 perl 的 IO 切换为 utf-8 是不是正确?

Posted

技术标签:

【中文标题】使用 Plack 和 Middlewares 时将默认 perl 的 IO 切换为 utf-8 是不是正确?【英文标题】:It is correct to switch the default perl's IO to utf-8 while using Plack and Middlewares?使用 Plack 和 Middlewares 时将默认 perl 的 IO 切换为 utf-8 是否正确? 【发布时间】:2012-06-16 05:59:58 【问题描述】:

两个起点:

在his answer to Why does modern Perl avoid UTF-8 by default?tchrist 中指出了确保在Perl 中正确处理Unicode 所需的52 件事。答案显示了带有一些use 语句的样板代码。关于使用 Unicode 的一个类似问题是How to make "use My::defaults" with modern perl & utf8 defaults?

PSGI spec 在设计上是面向字节的。我有责任对所有内容进行编码/解码,因此对于 Plack 应用程序,正确的方法是对输出进行编码和对输入进行解码,例如:

use Encode;
my $app = sub 
    my $output = encode_utf8( myapp() );
    return [ 200, [ 'Content-Type' =>'text/plain' ], [ $str ] ];
;

使用是否正确

use uni::perl; # or any similar

在 PSGI 应用程序和/或我的模块中?

uni::perl 将 Perl 的默认 IO 更改为 UTF-8,因此:

use open qw(:std :utf8);
binmode(STDIN,   ":utf8");
binmode(STDOUT,  ":utf8");
binmode(STDERR,  ":utf8");

这样做会破坏 Plack 或其中间件中的某些内容吗?或者是为 Plack 编写应用程序的唯一正确方法是在打开时显式编码/解码,所以没有 open pragma?

【问题讨论】:

Plack 是写入 STDOUT 还是从 STDIN 读取?如果是这样,那几乎肯定是错误的(除非它们也是 Plack 中的错误)。我说“几乎”是因为在 Plack 中使用 binmode 会让它不在乎。 PS - 现在您知道为什么默认情况下不这样做了;它会破坏东西。 我希望@miyagawa gurusan 会告诉更多.. :) 我理解为什么 utf8 不是默认的,但是,(IMO)新的 CPAN 模块应该使用“perl -CSDA”开发" 或考虑到env PERL_UNICODE。而且宫川肯定会在日本环境中使用它,所以,应该知道正确的方法.. ;) 我认为您列出的“正确方法”已被破坏。 text/plain 需要一个字符集,以便对方知道字节代表什么以及如何解码它们。 @Ashley,是的 - 和thanx。该片段也有另一个错误($str vs $output)。但这与问题无关。 【参考方案1】:

在现代 GNU/Linux 系统上,您应该在全局范围内完全切换到 UTF-8。这意味着设置

LANG="xx_YY.UTF-8"
PERL_UNICODE=SDAL
PERL5OPT=-Mutf8

在您的/etc/environment/etc/sysconfig/i18n/etc/default/locale 或任何您的系统配置文件中。因为RHEL/Centos bug 我将/etc/environment 符号链接到sysconfig/i18n

依赖二进制输入的脚本应在 STDIN/OUT/ERR(?) 或 use open pragma 上设置 binmode,或者应使用 -C0 选项调用。

问题是某些DBD 驱动程序有问题,例如DBD::JDBC,必须手动设置utf8标志。

use Encode qw/_utf8_on/;
map  _utf8_on $_;  @strings;

【讨论】:

【参考方案2】:

您真的不想在 Plack 上将 STDIN/STDOUT 默认设置为 UTF-8 模式,因为您不知道它们是否会是二进制数据传输。例如。如果这些文件句柄是 FastCGI 协议连接器,它们将携带编码的二进制结构而不是 UTF-8 文本。因此,它们不得定义编码层,否则这些二进制结构将被破坏或视为无效而被拒绝。

【讨论】:

以上是关于使用 Plack 和 Middlewares 时将默认 perl 的 IO 切换为 utf-8 是不是正确?的主要内容,如果未能解决你的问题,请参考以下文章

从计划任务运行 perl Plackup 脚本

python爬虫人门Scrapy框架之Downloader Middlewares

Scrapy框架: middlewares.py设置

爬虫框架Scrapy之Downloader Middlewares

Download Middlewares的作用?如何自定义ItemPipeline,写出需要实现的

scrapy-middlewares