You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#!/usr/bin/env python# -*- coding: utf-8 -*-# Note: To use the 'upload' functionality of this file, you must:# $ pip install twineimportioimportosimportsysfromshutilimportrmtreefromsetuptoolsimportfind_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:
withio.open(os.path.join(here, 'README.md'), encoding='utf-8') asf:
long_description='\n'+f.read()
exceptFileNotFoundError:
long_description=DESCRIPTION# Load the package's __version__.py module as a dictionary.about= {}
ifnotVERSION:
withopen(os.path.join(here, NAME, '__version__.py')) asf:
exec(f.read(), about)
else:
about['__version__'] =VERSIONclassUploadCommand(Command):
"""Support setup.py upload."""description='Build and publish the package.'user_options= []
@staticmethoddefstatus(s):
"""Prints things in bold."""print('\033[1m{0}\033[0m'.format(s))
definitialize_options(self):
passdeffinalize_options(self):
passdefrun(self):
try:
self.status('Removing previous builds…')
rmtree(os.path.join(here, 'dist'))
exceptOSError:
passself.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,
},
)
The text was updated successfully, but these errors were encountered:
python setup.py 浅析
setuptools.setup() 参数说明
packages
对于所有 packages 列表里提到的纯 Python 模块做处理
需要在 setup 脚本里有一个包名到目录的映射。
默认对于 setup 脚本所在目录下同名的目录即视为包所在目录。
当你在 setup 脚本中写入 packages = ['foo'] 时, setup 脚本的同级目录下可以找到
foo/__init__.py
。如果没有找到对应文件,disutils 不会直接报错,而是给出一个告警然后继续进行有问题的打包流程。package_dir
阐明包名到目录的映射,见 packages
键: 代表了包的名字,空的包名则代表 root package(不在任何包中的顶层包)。
值: 代表了对于 setup 脚本所在目录的相对路径.
指明包位于 lib/foo/,
lib/foo/__init__.py
这个文件存在另一种方法则是直接将 foo 这个包的内容全部放入 lib 而不是在 lib 下建一个 foo 目录
一个在 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:
注意,此处引入或者排除的文件必须是 package 内的文件
在 MANIFEST.in 引入 include mydata.data 将不起作用
exclude_package_date
排除一部分包文件
{'myapp':['.gitignore]},就表明只排除 myapp 包下的所有.gitignore 文件。
data_files
指定其他的一些文件(如配置文件)
规定了哪些文件被安装到哪些目录中。
如果目录名是相对路径(比如 bitmaps),则是相对于 sys.prefix(/usr) 或 sys.exec_prefix 的路径。
否则安装到绝对路径(比如 /etc/init.d )。
cmdclass
定制化命令,通过继承 setuptools.command 下的命令类来进行定制化
这样可以通过
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
运行环境目录结构为:
打包工程
python3 setup.py sdist bdist_wheel
在 dist 下生成了安装包
进入虚拟环境
source venv/bin/activate
安装包
pip install ./dist/legit-1.0.1.tar.gz
安装过程分析
venv/lib/python2.7/site-packages/
下安装了 legit 及依赖包venv/bin
下新增可执行文件 legit, 内容为此时,可以直接运行
setup.py 分析
'console_scripts': ['legit = legit.cli:cli',]
生成可执行控制台程序,程序名为 legit, 运行 legit.cli 中的 cli()函数。最终会在 bin/ 下生成 legit 可执行 py 文件,调用制定的函数setup.py 实例分析
kennethreitz/setup.py
The text was updated successfully, but these errors were encountered: