跳转到主要内容

Python扩展,包装ICU C++ API

项目描述

PyICU的README文件

欢迎

欢迎来到PyICU,这是一个包装ICU C++库的Python扩展。

ICU代表“国际组件Unicode”。这些是Unicode联盟的i18n库。它们实现了Unicode标准的大部分内容,许多其伴随的Unicode技术标准,以及大部分Unicode CLDR。

PyICU源代码托管在 https://gitlab.pyicu.org/main/pyicu

ICU主页是 https://icu.unicode.org/

还可以查看CLDR主页 http://cldr.unicode.org/

安装PyICU

PyICU是一个用C++实现的Python扩展,它包装了C/C++ ICU库。它还已知可以作为PyPy扩展工作。除非已经安装了pkg-config和ICU库以及头文件,否则从PyPI上的源代码构建PyICU不仅需要pip调用。许多操作系统分发预构建的二进制包的ICU和PyICU,请参见下文。

  • Mac OS X

    • 确保ICU已安装且可以通过pkg-config(因为icu-config自ICU 63.1起已被弃用)找到,可以通过遵循ICU构建说明,或使用Homebrew来实现。

      # install libicu (keg-only)
      brew install pkg-config icu4c
      
      # let setup.py discover keg-only icu4c via pkg-config
      export PATH="/usr/local/opt/icu4c/bin:/usr/local/opt/icu4c/sbin:$PATH"
      export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:/usr/local/opt/icu4c/lib/pkgconfig"
      
    • 使用与您的Python发行版相同的C++编译器安装PyICU (更多信息请参阅 这里

      # EITHER - when using a gcc-built CPython (e.g. from Homebrew)
      export CC="$(which gcc)" CXX="$(which g++)"
      # OR - when using system CPython or another clang-based CPython, ensure system clang is used (for proper libstdc++ https://gitlab.pyicu.org/main/pyicu/issues/5#issuecomment-291631507):
      unset CC CXX
      
      # avoid wheels from previous runs or PyPI
      pip install --no-binary=:pyicu: pyicu
      
    • ICU和PyICU的二进制文件也都可以通过Macports获得。关于混合二进制文件的限制可能同样适用。

      # see versions available
      /opt/local/bin/port search pyicu
      sudo /opt/local/bin/port install ...
      
  • Debian

    apt-get update
    
    # EITHER - from apt directly https://packages.debian.org/source/stable/pyicu
    apt-get install python3-icu
    # OR - from source
    apt-get install pkg-config libicu-dev
    pip install --no-binary=:pyicu: pyicu
    
  • Ubuntu:类似于Debian,您可以通过apt获得pyicu 软件包

  • Alpine Linux:您可以通过apk获得pyicu 软件包

  • NetBSD:您可以通过pkg_add获得pyicu 软件包

  • OpenBSD:您可以通过pkg_add获得pyicu 软件包

  • 其他操作系统:请参阅下文。

构建PyICU

有关从源代码构建Python、ICU和PyICU的说明,请参阅下一节。本节仅涉及从源代码构建PyICU,同时所有依赖项(如Python和ICU)已存在。

在构建PyICU之前,必须构建并安装ICU库。有关更多信息,请参阅每个系统的说明

PyICU可以从源代码使用setuptools构建,也可以使用buildpip构建。

  • 请确保pkg-config可用(自ICU 63.1起,icu-config程序已被弃用

    pkg-config --cflags --libs icu-i18n
    

    如果此命令返回错误或未返回预期的路径,请确保setup.py中的INCLUDESLFLAGSCFLAGSLIBRARIES字典包含您平台上的正确值。对于ICU版本[60, 74],-std=c++11必须出现在您的CFLAGS中或成为您C++编译器的默认值。从ICU 75开始,-std=c++17必须出现在您的CFLAGS中或成为您C++编译器的默认值。

  • 使用setuptools构建和安装PyICU

    python setup.py build
    sudo python setup.py install
    
  • 使用buildpip构建PyICU

    python -m build
    sudo python -m pip install dist/PyICU-<version>-<platform>.whl
    
  • 使用setuptools测试PyICU

    python setup.py test
    
  • 使用pytest测试PyICU

    python -m pytest
    

从源代码构建PyICU、Python 3和ICU

note_855中的说明包含将所有内容从源代码构建到自包含目录的完整步骤,而不修改任何系统目录。它们在M1 Mac上制作和测试过,但也可以修改和用于任何Unix环境。特别是,它们概述了在没有icu-config或pkg-config的情况下从源代码构建PyICU的方法。

运行PyICU

  • Mac OS X 确保在DYLD_LIBRARY_PATH中包含包含ICU库的目录的路径。

  • Linux & Solaris 确保在LD_LIBRARY_PATH中包含包含ICU库的目录的路径,或者您已将相应的-rpath参数添加到LFLAGS中。

  • Windows 确保在PATH中包含包含ICU DLLs的目录的路径。

可用内容

请参阅CHANGES文件,以获取更改和新增内容的最新日志。

API文档

PyICU没有API文档。ICU的API文档位于https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/,以下模式可用于将C++ API转换为相应的Python API。

字符串

ICU字符串类型,UnicodeString,是指向一个可变数组UChar Unicode 16位宽字符的类型,详细信息请参见这里。Python 3的str类型在此这里进行了描述。Python 2的unicode类型在此进行了描述。

由于它们之间的差异,当跨越C++边界时,ICU和Python的字符串对象不会合并为同一类型,而是进行转换。

接受UnicodeString参数的ICU API已被重载,以接受Python 3的str或Python 2的unicode对象作为参数。Python 2的str对象将自动使用utf-8编码解码为ICU字符串。

要使用编码为非utf-8的编码将Python 3的bytes或Python 2的str对象转换为ICU的UnicodeString,请使用构造函数UnicodeString(str, encodingName)

ICU的C++ API以多种方式接受和返回UnicodeString参数:按值、按指针或按引用。当一个ICU C++ API被文档记录为接受一个UnicodeString引用参数时,可以安全地假设存在几个相应的PyICU Python API,使得它以更简单的方式访问。

例如,文档记录为这里'UnicodeString &Locale::getDisplayName(UnicodeString &)' API可以从Python以多种方式调用。

  1. ICU方式

     >>> from icu import UnicodeString, Locale
     >>> locale = Locale('pt_BR')
     >>> string = UnicodeString()
     >>> name = locale.getDisplayName(string)
     >>> name
     <UnicodeString: 'Portuguese (Brazil)'>
     >>> name is string
     True                  <-- string arg was returned, modified in place
    
  2. Python方式

     >>> from icu import Locale
     >>> locale = Locale('pt_BR')
     >>> name = locale.getDisplayName()
     >>> name
     'Portuguese (Brazil)'
    

    分配了一个UnicodeString对象并将其转换为Python的str对象。

UnicodeString可以使用Python 3的str()或Python 2的unicode()构造函数转换为Python unicode字符串。通常的len()、比较、`[]`和`[:]`操作符都是可用的,而且切片不是只读的,`+=`也是可用的,因为UnicodeString是可变的。例如

>>> name = locale.getDisplayName()
'Portuguese (Brazil)'
>>> name = UnicodeString(name)
>>> name
<UnicodeString: 'Portuguese (Brazil)'>
>>> str(name)
'Portuguese (Brazil)'
>>> len(name)
19
>>> str(name)
'Portuguese (Brazil)'
>>> name[3]
't'
>>> name[12:18]
<UnicodeString: 'Brazil'>
>>> name[12:18] = 'the country of Brasil'
>>> name
<UnicodeString: 'Portuguese (the country of Brasil)'>
>>> name += ' oh joy'
>>> name
<UnicodeString: 'Portuguese (the country of Brasil) oh joy'>

错误报告

C++ ICU库不使用C++异常来报告错误。ICU C++ API通过一个UErrorCode引用参数返回错误。所有这样的API都被Python API包装,省略了该参数,并抛出一个ICUError Python异常。对于同时接受一个ParseError和一个UErrorCode的ICU API也是如此,它们都应该省略。

例如,文档记录为这里'UnicodeString &DateFormat::format(const Formattable &, UnicodeString &, FieldPosition &, UErrorCode &)' API可以从Python用以下方式调用

>>> from icu import DateFormat, Formattable
>>> df = DateFormat.createInstance()
>>> df
<SimpleDateFormat: M/d/yy h:mm a>
>>> f = Formattable(940284258.0, Formattable.kIsDate)
>>> df.format(f)
'10/18/99 3:04 PM'

当然,也可以使用文档记录为这里的更简单的'UnicodeString &DateFormat::format(UDate, UnicodeString &)'

>>> from icu import DateFormat
>>> df = DateFormat.createInstance()
>>> df
<SimpleDateFormat: M/d/yy h:mm a>
>>> df.format(940284258.0)
'10/18/99 3:04 PM'

日期

ICU使用一个称为UDate的双精度浮点类型,代表自1970年1月1日UTC以来经过的毫秒数,用于日期。

在Python中,time模块的time()函数返回自1970年1月1日UTC以来的秒数。由于这个差异,浮点值在传递给接受UDate的API时要乘以1000,在作为UDate返回时要除以1000。

带有或没有时区信息的Python的datetime对象也可以与接受UDate参数的API一起使用。datetime对象在进入C++层时会转换为UDate

数组

许多ICU API接受数组参数。需要从Python传递一个包含数组元素类型的元素列表。

StringEnumeration

ICU 的 StringEnumeration 有三个 next 方法:next() 返回 str 对象,unext() 在 Python 3 中返回 str 对象,在 Python 2 中返回 unicode 对象,snext() 返回 UnicodeString 对象。这些方法中的任何一个都可以用作迭代器,可以使用 Python 内置的 iter 函数。

例如,假设 e 是一个 StringEnumeration 实例

e = TimeZone.createEnumeration()
[s for s in e] # a list of 'str' objects
[s for s in iter(e.unext, '')] # a list of 'str' or 'unicode' objects
[s for s in iter(e.snext, '')] # a list of 'UnicodeString' objects

时区

ICU 的 TimeZone 类型可以通过 ICUtzinfo 类型包装,以便与 Python 的 datetime 类型一起使用。例如

from datetime import datetime
tz = ICUtzinfo(TimeZone.createTimeZone('US/Mountain'))
datetime.now(tz)

或者,更简单一点

tz = ICUtzinfo.getInstance('Pacific/Fiji')
datetime.now(tz)

要获取默认时区,请使用

defaultTZ = ICUtzinfo.getDefault()

要获取时区的 ID,请使用 tzid 属性或将时区强制转换为字符串

ICUtzinfo.getInstance('Pacific/Fiji').tzid -> 'Pacific/Fiji'
str(ICUtzinfo.getInstance('Pacific/Fiji')) -> 'Pacific/Fiji'

进一步阅读

单元测试 中有更多实际 PyICU 使用的示例。

还有一些从 ICU C/C++ 端口迁移的 示例

最后但同样重要的是,这份 速查表 提供了一些有用的示例。

项目详情


发布历史 发布通知 | RSS 源

下载文件

下载适用于您平台的文件。如果您不确定该选择哪个,请了解有关 安装包 的更多信息。

源分布

PyICU-2.13.1.tar.gz (262.4 kB 查看散列)

支持者

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面