Python

来自百合仙子's Wiki
跳转到导航 跳转到搜索

问题处理与技巧

国际化

程序中使用:[1]

import os
import gettext
APP_NAME = "程序名"
LOCALE_DIR = os.path.abspath("locale")
if not os.path.exists(LOCALE_DIR):
    LOCALE_DIR = "/usr/share/locale"
gettext.bindtextdomain(APP_NAME, LOCALE_DIR)
gettext.textdomain(APP_NAME)
_ = gettext.gettext

然后接下来的操作见 gettext。参见 C#国际化

有用的模块调用命令

简单的 HTTP 文件共享:(在8000端口共享当前文件夹)

python2 -m SimpleHTTPServer
python3 -m http.server
python -m smtpd -n -c DebuggingServer localhost:2525
python -m pickle FILES

当前行号与函数名

[2]

sys._getframe().f_code.co_name
sys._getframe().f_back.f_code.co_name

Windows 相关

BOM 的处理

使用 utf-8-sig 编码可在存在 BOM 时将其跳过,写文件时会自动添加 BOM。

subprocess 调用程序的搜索路径

不会使用 %PATH% 环境变量,见 Windows API#CreateProcess。可使用os.system 来绕过此问题。

代码页

Python 的默认编码(locale.getpreferredencoding())使用 GetACP() 函数来取得系统的代码页。此代码页不会被 chcp 命令改变

模块和导入

导入指定 Python 文件,作为指定包的子模块:

import importlib.machinery
import package
file = 'path/to/file'
loader = importlib.machinery.SourceFileLoader('package.name', file)
mod = loader.load_module()
# necessary, or can't find name when from-importing and using via attribute
package.name = mod

自定义模块导入

从当前目录下导入 JSON 文件:

import os
import sys
import json
import importlib.abc

class JSONFinder(importlib.abc.PathEntryFinder):
  def find_module(self, fullname, path=None):
    if os.path.isfile(fullname + '.json'):
      return JSONLoader(fullname + '.json')

class JSONLoader(importlib.abc.Loader):
  def __init__(self, filepath):
    self.filepath = filepath

  def exec_module(self, mod):
    with open(self.filepath) as f:
      data = json.load(f)
    mod.__dict__.update(data)
    mod.__file__ = self.filepath
    mod.__spec__.origin = self.filepath
    mod.__spec__.has_location = True

sys.meta_path.append(JSONFinder())

import config

print(config, vars(config))

设置

# 在命令行中,Tab实现补全功能
import rlcompleter, readline
readline.parse_and_bind('tab: complete')

调用 readline 中的 rl_callback_read_char

可以使用ctypes来调用,并且可以同时使用 readline 标准库。

#!/usr/bin/env python3
# vim:fileencoding=utf-8

import sys
import readline
import ctypes
import ctypes.util

rllib_path = ctypes.util.find_library('readline')
rllib = ctypes.CDLL(rllib_path)

def callback(s):
  if s is None:
    rllib.rl_callback_handler_remove()
    sys.stdout.write('\n')
    sys.exit()
  elif not s:
    pass
  else:
    print('%s.' % s.decode())
    # 这样也可以
    # print(readline.get_line_buffer()+'.')

cbfunc = ctypes.CFUNCTYPE(None, ctypes.c_char_p)

rllib.rl_callback_handler_install.restype = None
rllib.rl_callback_handler_install(ctypes.c_char_p(b">> "), cbfunc(callback))

while True:
  rllib.rl_callback_read_char()

对象系统

在 Python 2.7 中,无法在非该类的实例上调用该类的方法,而在 Python 3(已测试: 3.2、3.3)中可以。示例:

class T(object):
  def m(self):
    print(self)

a = object()
T.m(a)

结果如下:

$ python2 ~tmp/t.py
Traceback (most recent call last):
  File "/home/lilydjwg/tmpfs/t.py", line 8, in <module>
    T.m(a)
TypeError: unbound method m() must be called with T instance as first argument (got object instance instead)
$ python3 ~tmp/t.py
<object object at 0x7f92f2424080>

环境变量

PYTHONSTARTUP
交互式解释器载入时加载的配置文件
PYTHONPATH
查找库文件的路径(目录),与 PATH 变量一样以冒号分隔

编译与安装

Python 3.7

#常用模块依赖
sudo apt-get install libreadline-dev libexpat1-dev libsqlite3-dev libssl-dev libncursesw5-dev
sudo apt-get install libbz2-dev liblzma-dev

../configure --enable-shared --with-threads --with-computed-gotos --enable-ipv6 --with-system-expat --with-dbmliborder=gdbm:ndbm --with-system-ffi --with-system-libmpdec --enable-loadable-sqlite-extensions --without-ensurepip --with-optimizations
make
sudo make install
# 或者不覆盖同系列
# sudo make altinstall
sudo ldconfig

Python 2.7

(安装于 CentOS 6,尚不完整)

yum install -y expat-devel

wget https://www.python.org/ftp/python/$ver/Python-$ver.7.11.tar.xz
tar xf Python-$ver.tar.xz
cd Python-$ver
./configure --enable-shared --with-threads --with-computed-gotos --enable-ipv6 --with-valgrind --with-wide-unicode --with-system-expat --with-system-ffi
make -j$(nproc)
make altinstall
echo /usr/local/lib > /etc/ld.so.conf.d/local.conf
ldconfig

# 安装 pip
wget https://bootstrap.pypa.io/get-pip.py
python2.7 get-pip.py

交叉编译

[3]

参见:交叉编译记录

编辑Modules/Setup.dist,把需要用到的模块,去掉注释。注意模块依赖的库也要安装。注意 readline 中要去掉-ltermcap

配置:

# 根据实际情况配置
mkdir build-arm && cd build-arm
echo ac_cv_file__dev_ptmx=yes > config.site
echo ac_cv_file__dev_ptc=no >> config.site
export CONFIG_SITE=config.site
../configure --host=arm-dyne-linux-gnueabi --build=arm --enable-shared --disable-ipv6

开始编译:

make python

如果出现无法执行Parser/pgen的情况,修改pyconfig.hSIZEOF_LONG为正确值(在64位系统上是8),然后编译:

rm Parser/*
make CC=gcc Parser/pgen

然后再把pyconfig.h修改回原值并修改文件的时间戳:

touch -t 200001010000 pyconfig.h

再次进行编译。如果过程中有.o文件格式不正确,可删除后重试:

rm Parser/*.o
touch -t 210001010000 Parser/pgen

如果最后链接时出现clock_getrescrypt符号找不到,可在最后的链接命令上加上-lrt -lcrypt

打包安装

可以将 Python 标准库打包为 zip 格式以节省空间:

# 清理不需要的文件
rm **/*.pyc?
perl-rename 's=__pycache__/([^.]+).cpython-33.pyo$=\1.pyo=' **/*.pyo
rmdir **/*(/)
zip -9r ../python33.zip .

二进制文件后缀

依据不同的编译参数,Python3.2 的可执行文件和库文件有一些后缀(按同时包含时出现的顺序): [4]

d
--with-pydebug
m
--with-pymalloc
u
--with-wide-unicode

使用sys.abiflags可以得到这个值。

参见

相关软件

JavaScript / 浏览器端工具

  • Brython, A Python 3 implementation for client-side web programming. 不需要手工编译。
  • pythonium, Python 3 to Javascript translator written in Python. 需要编译,需要引入自身的代码。与 JavaScript 间的数据结构不透明。

基于 Python 平台的语言

  • Hy: 编译成 Python 的 Lisp 方言
  • dg: 编译成 Python 的类 Haskell 语言

外部链接

资源

教程

This opinionated guide exists to provide both novice and expert Python developers a best-practice handbook to the installation, configuration, and usage of Python on a daily basis.

Python 3

设计

其它

TODO

整理这些链接

参考资料