# CyPkgDemo

CyPkgDemo 是一个以 Cython - Python 联合编译、包装发布为背景的 Demo 包。

## 使用方法

- 可以通过 `pip install CyPkgDemo` 将 CyPkgDemo 安装至 "root" package 下（建议使用虚拟环境），
在文件中使用常规方式 `import cypkgdemo` 引用即可。

- 可以下载源文件，使用 `python setup.py install` 安装。

## 说明

项目中的 `setup.py` 是主要内容，其中包含了如何为每一个 `.pyx` 文件构造 Extension 的方法（通用可移
植），还有一些包命名时的注意事项。

如果获取了源发行包（source distribution），可以运行 `test.py` 进行测试。注意，如果要从源发行包的根
目录运行，必须先执行 `python setup.py build_ext --inplace` 生成链接库，否则会报出 `ImportError`
（这是由于 python 在解析模块导入位置的时候，会遵循如下顺序：

1. built-ins

2. `sys.path`：

    1. 脚本执行的位置，即当前路径；

    2. 环境变量中的 `PYTHONPATH`，即 .bash_profile；

    3. 安装 python 时的依赖位置。
    
故源发行包目录下的 cypkgdemo （没有生成链接库文件）会覆盖可能已安装至 site-packages 的 cypkgdemo，
从而抛出 `ImportError`）。另一种解决方案是切换至源发行包目录外的位置执行 `setup.py`。


## 开发的一般步骤

一般而言，对于一个包含了多个 Python 和 Cython 源文件的项目，每个模块在导入同一项目下的其他模块时，都
应当采用相对于最顶层包的绝对路径（例如，在这里就是 `from cypkgdemo.atoi import / cimport ...`）。

若只有纯 Python 文件，最顶层包在源文件夹中的名字和安装后的包名可以不相同，例如在源项目中，`cypkgdemo` 
文件夹可以改名为 `src`, 同时须在 setup.py 中为 `setup()` 指定 `package_dir={cypkgdemo: src}`。
若还包含 Cython 文件，则二者名字应当一致。

在编写完源代码后，先运行 `python setup.py build_ext --inplace`，这样便可方便在项目目录下直接进行
测试，测试时按照 `from cypkgdemo.atoi import ...` 的方式导入模块即可。

在进行安装测试时，运行 `python setup.py install --record ./record.txt`，或者直接运行 
`pip install .`，此时上一步测试前 `build_ext` 得到的链接库文件不会被包含进安装目录。

采用以下步骤上传至 PyPI（同样，`build_ext --inplace` 得到的链接库文件不会被包含）:
```python
python setup.py sdist bdist_wheel
twine upload --repository-url https://test.pypi.org/legacy/ dist/*  # Upload to Test PyPI
# twine upload dist/*  # To PyPI
```

注意，如果是发布源文件（`python setup.py sdist`），开发者应当安装有 Cython，以便使生成的 C 文件包含
进源发行包中（这样用户可以不用安装有 Cython）。

采用以下方式安装之前上传的包：
```python
python3 -m pip install --index-url https://test.pypi.org/simple/ CyPkgDemo  # From Test PyPI
# pip install CyPkgDemo  # From PyPI

```
注意第一种方式会将当前目录导入 `sys.path`，所以若是在项目根目录（setup.py 所在的那一层）运行安装代码，
则应将其改为 `pip install ...`，否则会提示 "Requirement already satisfied"。或者换到项目外运行
安装代码（原理同上）。

