(LTS) Misc
LC_*
环境变量
参考资料:
- https://sites.ualberta.ca/dept/chemeng/AIX-43/share/man/info/C/a_doc_lib/aixbman/baseadmn/locale_env.htm
- https://www.ibm.com/docs/en/aix/7.3?topic=locales-understanding-locale-environment-variables
LC_*
环境变量用于设置区域信息, 主要包括这些:
高优先级:
LC_ALL
: 设置此值时, 则会覆盖其余LC_*
的取值LC_COLLATE
: 影响字符的排序规则LC_CTYPE
: 影响字符分类(字母,数字,符号等)以及字符集的范围以及对应的字节表示
中优先级:
LC_MESSAGES
: 控制程序显示的提示和错误信息的语言LC_MONETARY
: 控制货币的符号以及货币符号的位置LC_NUMERIC
: 控制数字的输出格式(例如每三位用逗号隔开)LC_TIME
: 控制日期显示格式
低优先级:
LANG
: 当LC_ALL
未被设置时, 且LC_*
变量未设置时, 那么LC_*
变量将使用LANG
的取值
以上这些变量的常见取值有
C
,POSIX
: 这两者完全等价, 字符集仅包括 ASCII, 是最简单, 与区域无关的默认值, 设置此值时在 C 语言环境下可保证一致行为, 也是操作系统启动时的默认值C.UTF-8
: 对C
的扩展, 主要是扩展字符集为 UTF-8, 但与区域无关. 当希望在 C 语言环境下保证一致行为, 且希望采用 UTF-8 字符集时, 推荐采用此值.en_US.utf8
: 字符集为 UTF-8, 日期、时间、货币和其他格式符合美国习惯zh_CN.utf8
: 字符集为 UTF-8, 日期、时间、货币和其他格式符合中国习惯
上述优先级的设定可以用下面的 python 代码示意:
keys = ["LC_COLLATE", "LC_CTYPE", "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", "LC_TIME"]
lc_vars = {key: "C" for key in keys} # C 是默认值
for key in keys:
if os.environ.get("LC_ALL", ""):
lc_vars[key] = os.environ.get("LC_ALL", "")
elif os.environ.get(key, ""):
lc_vars[key] = os.environ.get(key, "")
elif os.environ.get("LANG", ""):
lc_vars[key] = os.environ.get("LANG", "")
除了上述变量以外, 使用 locale
命令, 还会看到这些变量:
LANGUAGE
主要用于翻译设置的优先级, 例如:LANGUAGE=fr:en:de
, 表明翻译优先级由高到低为: 法语,英语,德语LC_PAPER
: 纸张大小LC_NAME
: 人名的书写格式LC_ADDRESS
: 地址的书写格式LC_TELEPHONE
: 电话号码格式LC_MEASUREMENT
: 度量衡LC_IDENTIFICATION
: 特定标识?
所以, 比较省事的做法是直接设置 LC_ALL
变量. 最后, 以上所有的变量以及优先级仅对严格遵循 POSIX 标准的应用程序有效. 并且这些变量通常是在“软件本地化”(国际化:i18n 和本地化:l10n)的场景下才会用到
以下是一个关于 LC_TIME
的示例
import locale
from datetime import datetime
# 可以尝试设置为: C, C.UTF-8, en_US.UTF-8, zh_CN.UTF-8
locale.setlocale(locale.LC_TIME, 'C')
# 获取并打印当前系统的日期格式
current_locale = locale.getlocale(locale.LC_TIME)
print("当前 LC_TIME 本地化设置:", current_locale)
# 打印当前时间, 注意: 这里用的格式化方式是 %c
now = datetime.now()
print("当前时间:", now.strftime('%c'))
输出:
# 设置为 C 或 POSIX 时
当前 LC_TIME 本地化设置: (None, None)
当前时间: Sun Sep 22 11:22:24 2024
# 设置为 en_US.UTF-8 时
当前 LC_TIME 本地化设置: ('en_US', 'UTF-8')
当前时间: Sun 22 Sep 2024 11:22:51 AM
# 设置为 zh_CN.UTF-8 时
当前 LC_TIME 本地化设置: ('zh_CN', 'UTF-8')
当前时间: 2024年09月22日 星期日 10时59分10秒
# 设置为 C.UTF-8 时, 不同的环境配置可能有所不同
当前 LC_TIME 本地化设置: ('en_US', 'UTF-8')
当前时间: Sun 22 Sep 2024 11:22:51 AM
(1) 注意: 如果出现 locale.Error: unsupported locale setting
这种报错, 可以使用 locale 命令进行检查和添加:
# 查看系统中支持的语言环境
locale -a
# 安装语言环境
sudo locale-gen zh_CN.UTF-8
# 查看所有LC相关的环境变量的设置情况
locale
# Debian/Ubuntu 系统 LC 相关变量的默认值设置文件: /etc/default/locale
# 修改后可以 source 或重新登录使其生效
# 安装/删除语言环境
# 可以直接修改 /etc/locale.gen 文件, 然后执行
sudo locale-gen
(2) 注意: 当设置为 C.UTF-8
时, 显示的值可能会与系统默认的 LC_*
变量有关
Little Endian vs Big Endian
在 C 语言的虚拟内存中, 假设有一个 32 位的整数数组, 用来存储: [1, 2, 3]
, 假设数组的起始地址是 0x100
, 那么无论是 Little Endian 还是 Big Endian, 0x100, 0x101, 0x102, 0x103
这 4 个字节用于存储 1, 0x104, 0x105, 0x106, 0x107
这 4 个字节用于存储 2, 0x108, 0x109, 0x10A, 0x10B
这 4 个字节用于存储 3, 另外在一个字节内部, 总是高位在前, 低位在后
0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A, 0x10B
# Big Endian (按比特值)
00000000, 00000000, 00000000, 00000001
00000000, 00000000, 00000000, 00000002
00000000, 00000000, 00000000, 00000003
# Little Endian (按比特值)
00000001, 00000000, 00000000, 00000000
00000002, 00000000, 00000000, 00000000
00000003, 00000000, 00000000, 00000000
在文件的场景下, 文件在进行网络传输或是U盘拷贝时,其字节顺序不会发生变化(拷贝和传输时,并不知道文件中哪些字节应该组合在一起形成有意义的内容,因此这些过程字节顺序只能是原封不动的). 如何理解文件中的字节由写入和读取程序.
import struct
with open("x.dat", "wb") as fw:
fw.write(struct.pack("<I", 1)) # b'\x01\x00\x00\x00'
fw.write(struct.pack(">I", 2)) # b'\x00\x00\x00\x02'
with open("x.dat", "rb") as fr:
x = fr.read(8) # b'\x01\x00\x00\x00\x00\x00\x00\x02'
struct.unpack("<I", x[:4]) # (1,)
struct.unpack(">I", x[4:]) # (2,)
在上面的例子中, 实际上是写入程序与读取程序约定了如下协议: 文件中包含两个 int32 的数字, 第一个数字采用 Little Endian, 第二个数字采用 Big Endian.
numpy.ndarray.newbyteorder
# S 表示使用相反的字节序
np.array([1, 2], dtype=np.int16).newbyteorder('S') # array([256, 512], dtype=int16)
# = 和 I 表示使用相同的字节序
np.array([1, 2], dtype=np.int16).newbyteorder('=') # array([1, 2], dtype=int16)
np.array([1, 2], dtype=np.int16).newbyteorder('I') # array([1, 2], dtype=int16)
# 以下两个的输出与系统有关, 下面假设系统默认的是 Little Endian
import sys
sys.byteorder # 'little'
np.array([1, 2], dtype=np.int16).newbyteorder('<') # array([1, 2], dtype=int16)
np.array([1, 2], dtype=np.int16).newbyteorder('>') # array([256, 512], dtype=int16)