国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

python setup.py 淺析

sevi_stuo / 1323人閱讀

摘要:淺析參數說明對于所有列表里提到的純模塊做處理需要在腳本里有一個包名到目錄的映射。闡明包名到目錄的映射,見鍵代表了包的名字,空的包名則代表不在任何包中的頂層包。最終會在下生成可執行文件,調用制定的函數實例分析

python setup.py 淺析 setuptools.setup() 參數說明 packages

對于所有 packages 列表里提到的純 Python 模塊做處理
需要在 setup 腳本里有一個包名到目錄的映射。
默認對于 setup 腳本所在目錄下同名的目錄即視為包所在目錄。
當你在 setup 腳本中寫入 packages = ["foo"] 時, setup 腳本的同級目錄下可以找到 foo/__init__.py。如果沒有找到對應文件,disutils 不會直接報錯,而是給出一個告警然后繼續進行有問題的打包流程。

package_dir

闡明包名到目錄的映射,見 packages

package_dir = {"": "lib"}

鍵: 代表了包的名字,空的包名則代表 root package(不在任何包中的頂層包)。
值: 代表了對于 setup 腳本所在目錄的相對路徑.

packages = ["foo"]
package_dir = {"": "lib"}

指明包位于 lib/foo/, lib/foo/__init__.py 這個文件存在

另一種方法則是直接將 foo 這個包的內容全部放入 lib 而不是在 lib 下建一個 foo 目錄

package_dir = {"foo": "lib"}

一個在 package_dir 字典中的 package: dir 映射會對當前包下的所有包都生效, 所以 foo.bar 會自動生效. 在這個例子當中, packages = ["foo", "foo.bar"] 告訴 distutils 去尋找 lib/__init__.pylib/bar/__init__.py.

py_modules

對于一個相對較小的模塊的發布,你可能更想要列出所有模塊而不是列出所有的包,尤其是對于那種根目錄下就是一個簡單模塊的類型.
這描述了兩個包,一個在根目錄下,另一個則在 pkg 目錄下。
默認的“包:目錄”映射關系表明你可以在 setup 腳本所在的路徑下找到 mod1.py 和 pkg/mod2.py。
當然,你也可以用 package_dir 選項重寫這層映射關系就是了。

find_packages

packages=find_packages(exclude=("tests", "robot_server.scripts")),
exclude 里面是包名,而非路徑

include_package_data

引入包內的非 Python 文件
include_package_data 需要配合 MANIFEST.in 一起使用

MANIFEST.in:

include myapp/scripts/start.py
recursive-include myapp/static *
setup(
    name="MyApp",         # 應用名
    version="1.0",        # 版本號
    packages=["myapp"],   # 包括在安裝包內的Python包
    include_package_data=True    # 啟用清單文件MANIFEST.in
)

注意,此處引入或者排除的文件必須是 package 內的文件

setup-demo/
  ├ mydata.data      # 數據文件
  ├ setup.py         # 安裝文件
  ├ MANIFEST.in      # 清單文件
  └ myapp/           # 源代碼
      ├ static/      # 靜態文件目錄
      ├ __init__.py
      ...

在 MANIFEST.in 引入 include mydata.data 將不起作用

exclude_package_date

排除一部分包文件
{"myapp":[".gitignore]},就表明只排除 myapp 包下的所有.gitignore 文件。

data_files

指定其他的一些文件(如配置文件)

data_files=[("bitmaps", ["bm/b1.gif", "bm/b2.gif"]),
            ("config", ["cfg/data.cfg"]),
            ("/etc/init.d", ["init-script"])]

規定了哪些文件被安裝到哪些目錄中。
如果目錄名是相對路徑(比如 bitmaps),則是相對于 sys.prefix(/usr) 或 sys.exec_prefix 的路徑。
否則安裝到絕對路徑(比如 /etc/init.d )。

cmdclass

定制化命令,通過繼承 setuptools.command 下的命令類來進行定制化

class UploadCommand(Command):
    """Support setup.py upload."""
    ...

    def run(self):
        try:
            self.status("Removing previous builds…")
            rmtree(os.path.join(here, "dist"))
        except OSError:
            pass

        self.status("Building Source and Wheel (universal) distribution…")
        os.system("{0} setup.py sdist bdist_wheel --universal".format(sys.executable))

        self.status("Uploading the package to PyPI via Twine…")
        os.system("twine upload dist/*")

        self.status("Pushing git tags…")
        os.system("git tag v{0}".format(about["__version__"]))
        os.system("git push --tags")

        sys.exit()

setup(
    ...
    # $ setup.py publish support.
    cmdclass={
        "upload": UploadCommand,
    },
)

這樣可以通過 python setup.py upload 運行打包上傳代碼

install_requires

安裝這個包所需要的依賴,列表

tests_require

與 install_requires 作用相似,單元測試時所需要的依賴

虛擬運行環境下安裝包

以 legit 為例

下載 lgit 源碼
git clone https://github.com/kennethreitz/legit.git

創建虛擬運行環境
virtualenv --no-site-packages venv
運行環境目錄結構為:

venv/
├── bin
├── include
├── lib
├── local
└── pip-selfcheck.json

打包工程
python3 setup.py sdist bdist_wheel

.
├── AUTHORS
├── build
│?? ├── bdist.linux-x86_64
│?? └── lib.linux-x86_64-2.7
├── dist
│?? ├── legit-1.0.1-py2.py3-none-any.whl
│?? └── legit-1.0.1.tar.gz

在 dist 下生成了安裝包

進入虛擬環境
source venv/bin/activate

安裝包
pip install ./dist/legit-1.0.1.tar.gz

Successfully built legit args clint
Installing collected packages: appdirs, args, click, lint, colorama, crayons, smmap2, gitdb2, GitPython, ix, pyparsing, packaging, legit
Successfully installed GitPython-2.1.8 appdirs-1.4.3 rgs-0.1.0 click-6.7 clint-0.5.1 colorama-0.4.0 rayons-0.1.2 gitdb2-2.0.3 legit-1.0.1 packaging-17.1 yparsing-2.2.0 six-1.11.0 smmap2-2.0.3

安裝過程分析

venv/lib/python2.7/site-packages/ 下安裝了 legit 及依賴包

legit/venv/lib/python2.7/site-packages$ tree -L 1

.
├── appdirs-1.4.3.dist-info
├── appdirs.py
├── appdirs.pyc
├── args-0.1.0.dist-info
├── args.py
├── args.pyc
├── click
├── click-6.7.dist-info
├── clint
├── clint-0.5.1.dist-info
├── colorama
├── colorama-0.4.0.dist-info
├── crayons-0.1.2.dist-info
├── crayons.py
├── crayons.pyc
├── easy_install.py
├── easy_install.pyc
├── git
├── gitdb
├── gitdb2-2.0.3.dist-info
├── GitPython-2.1.8.dist-info
├── legit
├── legit-1.0.1.dist-info
├── packaging
├── packaging-17.1.dist-info
├── pip
├── pip-18.1.dist-info
├── pkg_resources
├── pyparsing-2.2.0.dist-info
├── pyparsing.py
├── pyparsing.pyc
├── setuptools
├── setuptools-40.6.2.dist-info
├── six-1.11.0.dist-info
├── six.py
├── six.pyc
├── smmap
├── smmap2-2.0.3.dist-info
├── wheel
└── wheel-0.32.2.dist-info

venv/bin 下新增可執行文件 legit, 內容為

#!/home/turtlebot/learn/python/legit/venv/bin/python

# -*- coding: utf-8 -*-
import re
import sys

from legit.cli import cli

if __name__ == "__main__":
    sys.argv[0] = re.sub(r"(-script.pyw?|.exe)?$", "", sys.argv[0])
    sys.exit(cli())

此時,可以直接運行

>>> legit
setup.py 分析
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import sys
from codecs import open  # To use a consistent encoding

from setuptools import setup  # Always prefer setuptools over distutils

APP_NAME = "legit"
APP_SCRIPT = "./legit_r"
VERSION = "1.0.1"


# Grab requirements.
with open("reqs.txt") as f:
    required = f.readlines()


settings = dict()


# Publish Helper.
if sys.argv[-1] == "publish":
    os.system("python setup.py sdist bdist_wheel upload")
    sys.exit()


if sys.argv[-1] == "build_manpage":
    os.system("rst2man.py README.rst > extra/man/legit.1")
    sys.exit()


# Build Helper.
if sys.argv[-1] == "build":
    import py2exe  # noqa
    sys.argv.append("py2exe")

    settings.update(
        console=[{"script": APP_SCRIPT}],
        zipfile=None,
        options={
            "py2exe": {
                "compressed": 1,
                "optimize": 0,
                "bundle_files": 1}})

settings.update(
    name=APP_NAME,
    version=VERSION,
    description="Git for Humans.",
    long_description=open("README.rst").read(),
    author="Kenneth Reitz",
    author_email="me@kennethreitz.com",
    url="https://github.com/kennethreitz/legit",
    packages=["legit"],
    install_requires=required,
    license="BSD",
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Intended Audience :: Developers",
        "Natural Language :: English",
        "License :: OSI Approved :: BSD License",
        "Programming Language :: Python",
        "Programming Language :: Python :: 2",
        "Programming Language :: Python :: 2.7",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.4",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
    ],
    entry_points={
        "console_scripts": [
            "legit = legit.cli:cli",
        ],
    }
)


setup(**settings)

packages=["legit"] 引入 legit 目錄下的所有默認引入文件

install_requires=required 指明安裝時需要額外安裝的第三方庫

"console_scripts": ["legit = legit.cli:cli",] 生成可執行控制臺程序,程序名為 legit, 運行 legit.cli 中的 cli()函數。最終會在 bin/ 下生成 legit 可執行 py 文件,調用制定的函數

setup.py 實例分析

kennethreitz/setup.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Note: To use the "upload" functionality of this file, you must:
#   $ pip install twine

import io
import os
import sys
from shutil import rmtree

from setuptools import find_packages, setup, Command

# Package meta-data.
NAME = "mypackage"
DESCRIPTION = "My short description for my project."
URL = "https://github.com/me/myproject"
EMAIL = "me@example.com"
AUTHOR = "Awesome Soul"
REQUIRES_PYTHON = ">=3.6.0"
VERSION = None

# What packages are required for this module to be executed?
REQUIRED = [
    # "requests", "maya", "records",
]

# What packages are optional?
EXTRAS = {
    # "fancy feature": ["django"],
}

# The rest you shouldn"t have to touch too much :)
# ------------------------------------------------
# Except, perhaps the License and Trove Classifiers!
# If you do change the License, remember to change the Trove Classifier for that!

here = os.path.abspath(os.path.dirname(__file__))

# Import the README and use it as the long-description.
# Note: this will only work if "README.md" is present in your MANIFEST.in file!
try:
    with io.open(os.path.join(here, "README.md"), encoding="utf-8") as f:
        long_description = "
" + f.read()
except FileNotFoundError:
    long_description = DESCRIPTION

# Load the package"s __version__.py module as a dictionary.
about = {}
if not VERSION:
    with open(os.path.join(here, NAME, "__version__.py")) as f:
        exec(f.read(), about)
else:
    about["__version__"] = VERSION


class UploadCommand(Command):
    """Support setup.py upload."""

    description = "Build and publish the package."
    user_options = []

    @staticmethod
    def status(s):
        """Prints things in bold."""
        print("