python setup.py_python setup.py 浅析

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__.py 和 lib/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 作用相似,单元测试时所需要的依赖

虚拟运行环境下安装包

下载 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 实例分析

#!/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 = '\n' + 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('\033[1m{0}\033[0m'.format(s))

def initialize_options(self):

pass

def finalize_options(self):

pass

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()

# Where the magic happens:

setup(

name=NAME,

version=about['__version__'],

description=DESCRIPTION,

long_description=long_description,

long_description_content_type='text/markdown',

author=AUTHOR,

author_email=EMAIL,

python_requires=REQUIRES_PYTHON,

url=URL,

packages=find_packages(exclude=('tests',)),

# If your package is a single module, use this instead of 'packages':

# py_modules=['mypackage'],

# entry_points={

# 'console_scripts': ['mycli=mymodule:cli'],

# },

install_requires=REQUIRED,

extras_require=EXTRAS,

include_package_data=True,

license='MIT',

classifiers=[

# Trove classifiers

# Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers

'License :: OSI Approved :: MIT License',

'Programming Language :: Python',

'Programming Language :: Python :: 3',

'Programming Language :: Python :: 3.6',

'Programming Language :: Python :: Implementation :: CPython',

'Programming Language :: Python :: Implementation :: PyPy'

],

# $ setup.py publish support.

cmdclass={

'upload': UploadCommand,

},

)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: nstall" 是用来做什么的? 这个命令是用来安装 Python 包的。在执行这个命令之前,需要先下载并解压缩 Python 包,然后进入包的根目录,执行命令即可安装该包。这个命令会将包安装到 Python 的 site-packages 目录下,以便在 Python 中使用该包。 ### 回答2: 指令 "python setup.py egg_i" 是用于在Python项目中创建和构建egg文件的命令。Egg文件是一种用于分发和安装Python软件包的文件格式。通过这个命令,我们可以将项目的源代码、依赖库和其他必要文件打包成一个egg文件,方便分享和安装。 这个命令的具体作用有以下几点: 1. 它会在当前目录执行setup.py文件,setup.py是一个用于配置Python安装和分发的脚本文件。 2. 使用egg_info选项,该命令会生成一个dist文件夹,并在该文件夹中创建一个包含项目元信息的egg-info目录。 3. egg-info 目录中包含了项目的名称、版本、作者、依赖关系等元信息,这些信息可以帮助正确地安装和使用项目。 4. Egg文件还可以包含项目的源代码、资源文件和其他必要的文件,以便于分发和安装。 5. 构建完成后,可以使用egg文件将项目部署到其他机器上,只需简单地将egg文件复制到目标机器,然后使用pip等工具进行安装即可。 总结来说,"python setup.py egg_i" 是一个用于创建和构建Python项目的egg文件的命令,通过将项目的源代码和必要文件打包成egg文件,方便项目的分享和安装。 ### 回答3: command "python setup.py egg_info" 是一个用于 Python 的命令行指令。这个命令是 setuptools 包的一部分,通常在安装第三方 Python 包时使用。 "egg_info" 是一个 setuptools 的功能,用于创建一个包含项目元数据的 ".egg-info" 目录。在这个目录下,包括了一些关于包名、作者、版本、依赖等信息的文件。这些元数据文件可以用来描述和管理项目的元信息。 通过在命令行中运行 "python setup.py egg_info",可以生成这个 ".egg-info" 目录。一些常见的用法是在安装第三方包之前先运行这个命令,这样可以确保项目的元数据被正确创建和保存。同时,这个命令也常用于开发环境中,当需要更新或修改项目的元数据时。 总结而言,command "python setup.py egg_info" 是用于在 Python 项目中创建 ".egg-info" 目录并管理项目的元数据的命令。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值