- 论坛徽章:
- 0
|
Its intents are:
To shorten the time needed to set up everything before starting the real work, in other words the boiler-plate code
To provide a standardized way to write packages
To ease the use of a test-driven development approach
To facilitate the releasing process
It is organized in the following four parts:
A common pattern for all packages that describes the similarities between all Python packages, and how distutils and setuptools play a central role
How generative programming
(http://en.wikipedia.org/wiki/Generative_programming)
can help this through the template-based approach
The package template creation, where everything needed to work is set
Setting up a development cycle
A Common Pattern for All Packages
The easiest way to organize the code of an application is to split it into several packages using eggs. This makes the code simpler, and easier to understand, maintain, and change. It also maximizes the reusability of each package. They act like components.
Applications for a given company can have a set of eggs glued together with a master egg.
Therefore, all packages can be built using egg structures.
This section presents how a namespaced package is organized, released, and distributed to the world through distutils and setuptools.
Writing an egg is done by layering the code in a nested folder that provides a common prefix namespace. For instance, for the Acme company, the common namespace can be acme. The result is a namespaced package.
For example, a package whose code relates to SQL can be called acme.sql. The best way to work with such a package is to create an acme.sql folder that contains the acme and then the sql folder:
![]()
setup.py, the Script That Controls Everything
The root folder contains a setup.py script, which defines all metadata as described in the distutils module, combined as arguments in a call to the standard setup function. This function was extended by the third-party library setuptools that provides most of the egg infrastructure.
The boundary between distutils and setuptools is getting fuzzy, and they might merge one day.
Therefore, the minimum content for this file is:
view source
print
?
1.from setuptools import setup
2.setup(name='acme.sql')
name gives the full name of the egg. From there, the script provides several commands that can be listed with the -help-commands option.
Standard commands:
build build everything needed to install
...
install install everything from build directory
sdist create a source distribution
register register the distribution
bdist create a built (binary) distribution
Extra commands:
develop install package in 'development mode'
...
test run unit tests after in-place build
alias define a shortcut
bdist_egg create an "egg" distribution
The most important commands are the ones left in the preceding listing. Standard commands are the built-in commands provided by distutils, whereas Extra commands are the ones created by third-party packages such as setuptools or any other package that defines and registers a new command.
sdist
The sdist command is the simplest command available. It creates a release tree where everything needed to run the package is copied. This tree is then archived in one or many archived files (often, it just creates one tar ball). The archive is basically a copy of the source tree.
This command is the easiest way to distribute a package from the target system independently. It creates a dist folder with the archives in it that can be distributed. To be able to use it, an extra argument has to be passed to setup to provide a version number. If you don’t give it a version value, it will use version = 0.0.0:
view source
print
?
1.from setuptools import setup
2.setup(name='acme.sql', version='0.1.1'
This number is useful to upgrade an installation. Every time a package is released, the number is raised so that the target system knows it has changed.
Let’s run the sdist command with this extra argument:
view source
print
?
01.$ python setup.py sdist
02.running sdist
03....
04.creating dist
05.tar -cf dist/acme.sql-0.1.1.tar acme.sql-0.1.1
06.gzip -f9 dist/acme.sql-0.1.1.tar
07.removing 'acme.sql-0.1.1' (and everything under it)
08.$ ls dist/
09.acme.sql-0.1.1.tar.gz
Under Windows, the archive will be a ZIP file.
The version is used to mark the name of the archive, which can be distributed and installed on any system having Python. In the sdist distribution, if the package contains C libraries or extensions, the target system is responsible for compiling them. This is very common for Linux-based systems or Mac OS because they commonly provide a compiler. But it is less usual to have it under Windows. That’s why a package should always be distributed with a pre-built distribution as well, when it is intended to run under several platforms.
The MANIFEST.in File
When building a distribution with sdist, distutils browse the package directory looking for files to include in the archive.
distutils will include:
All Python source files implied by the py_modules, packages, and scripts option
All C source files listed in the ext_modules option
Files that match the glob pattern test/test*.py
README, README.txt, setup.py, and setup.cfg files
Besides, if your package is under Subversion or CVS, sdist will browse folders such as .svn to look for files to include .sdist builds a MANIFEST file that lists all files and includes them into the archive.
Let’s say you are not using these version control systems, and need to include more files. Now, you can define a template called MANIFEST.in in the same directory as that of setup.py for the MANIFEST file, where you indicate to sdist which files to include.
This template defines one inclusion or exclusion rule per line, for example:
view source
print
?
1.include HISTORY.txt
2.include README.txt
3.include CHANGES.txt
4.include CONTRIBUTORS.txt
5.include LICENSE
6.recursive-include *.txt *.py
The full list of commands is available at
http://docs.python.org/dist/sdist-cmd.html#sdist-cmd
.
build and bdist
To be able to distribute a pre-built distribution, distutils provide the build command, which compiles the package in four steps:
build_py: Builds pure Python modules by byte-compiling them and copying them into the build folder.
build_clib: Builds C libraries, when the package contains any, using Python compiler and creating a static library in the build folder.
build_ext: Builds C extensions and puts the result in the build folder like build_clib.
build_scripts: Builds the modules that are marked as scripts. It also changes the interpreter path when the first line was set (!#) and fixes the file mode so that it is executable.
Each of these steps is a command that can be called independently. The result of the compilation process is a build folder that contains everything needed for the package to be installed. There’s no cross-compiler option yet in the distutils package. This means that the result of the command is always specific to the system it was build on.
Some people have recently proposed patches in the Python tracker to make distutils able to cross-compile the C parts. So this feature might be available in the future.
When some C extensions have to be created, the build process uses the system compiler and the Python header file (Python.h). This include file is available from the time Python was built from the sources. For a packaged distribution, an extra package called python-dev often contains it, and has to be installed as well.
The C compiler used is the system compiler. For Linux-based system or Mac OS X, this would be gcc. For Windows, Microsoft Visual C++ can be used (there’s a free command-line version available) and the open-source project MinGW as well. This can be configured in distutils.
The build command is used by the bdist command to build a binary distribution. It calls build and all dependent commands, and then creates an archive in the same was as sdist does.
Let’s create a binary distribution for acme.sql under Mac OS X:
view source
print
?
01.$ python setup.py bdist
02.running bdist
03.running bdist_dumb
04.running build
05....
06.running install_scripts
07.tar -cf dist/acme.sql-0.1.1.macosx-10.3-fat.tar .
08.gzip -f9 acme.sql-0.1.1.macosx-10.3-fat.tar
09.removing 'build/bdist.macosx-10.3-fat/dumb' (and everything under it)
10.$ ls dist/
11.acme.sql-0.1.1.macosx-10.3-fat.tar.gz acme.sql-0.1.1.tar.gz
Notice that the newly created archive’s name contains the name of the system and the distribution it was built under (Mac OS X 10.3).
The same command called under Windows will create a specific distribution archive:
C:acme.sql> python.exe setup.py bdist...C:acme.sql> dir dist25/02/2008 08:18 .25/02/2008 08:18 ..25/02/2008 08:24 16 055 acme.sql-0.1.win32.zip 1 File(s) 16 055 bytes 2 Dir(s) 22 239 752 192 bytes free
If a package contains C code, apart from a source distribution, it’s important to release as many different binary distributions as possible. At the very least, a Windows binary distribution is important for those who don’t have a C compiler installed.
A binary release contains a tree that can be copied directly into the Python tree. It mainly contains a folder that is copied into Python’s site-packages folder.
bdist_egg
The bdist_egg command is an extra command provided by setuptools. It basically creates a binary distribution like bdist, but with a tree comparable to the one found in the source distribution. In other words, the archive can be downloaded, uncompressed, and used as it is by adding the folder to the Python search path (sys.path).
These days, this distribution mode should be used instead of the bdist-generated one.
install
The install command installs the package into Python. It will try to build the package if no previous build was made and then inject the result into the Python tree. When a source distribution is provided, it can be uncompressed in a temporary folder and then installed with this command. The install command will also install dependencies that are defined in the install_requires metadata.
This is done by looking at the packages in the Python Package Index (PyPI). For instance, to install pysqlite and SQLAlchemy together with acme.sql, the setup call can be changed to:
from setuptools import setup
setup(name='acme.sql', version='0.1.1',
install_requires=['pysqlite', 'SQLAlchemy'])
When we run the command, both dependencies will be installed.
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/78/showart_1899922.html |
|