楼主: liuxf666
451 4

【学习笔记】Python - Organizing Larger Programs (Package & Module) [推广有奖]

  • 1关注
  • 3粉丝

已卖:70份资源

学科带头人

54%

还不是VIP/贵宾

-

威望
0
论坛币
13005 个
通用积分
409.9229
学术水平
109 点
热心指数
112 点
信用等级
103 点
经验
71218 点
帖子
1079
精华
0
在线时间
1538 小时
注册时间
2016-7-19
最后登录
2024-6-8

楼主
liuxf666 发表于 2019-5-22 21:54:05 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
1.1 Packages
A package in Python is just a special type of module. The defining characteristic of a package is that it can contain other modules, including other packages. So packages are a way to define hierarchies of modules in Python. This allows you to group modules with similar functionality together in ways that express their cohesiveness.

#1 - The __path__ attribute of packages
The package has a __path__ member and module does not have

This attribute is a list of filesystem paths indicating where urllib searches to find nested modules. This hints at the nature of the distinction between packages and modules: packages are generally represented by directories in the filesystem while modules are represented by single files.
Note: in Python 3 versions prior to 3.3, __path__ was just a single string, not a list.

#2 - Locating modules
  • how Python locates modules?
  • The answer is that Python checks the path attribute of the standard sys module, commonly referred to as sys.path .

#3 - The PYTHONPATH environment variable
The PYTHONPATH environment variable is a list of paths that are added to sys.path when Python starts. The format of PYTHONPATH is the same as PATH on your platform.

1.2 Implementing packages
  • To create a package, first you create the package’s root directory. This root directory needs to be in some directory on sys.path.
  • Then, in that root directory, you create a file called __init__.py . This file - which we’ll often call the package init file - is what makes the package a module. __init__.py can be (and often is) empty; its presence alone suffices to establish the package.

#1 - The role of __init__.py
  • the __init__.py is actually executed like any other module when you import the module

#2 - Adding functionality to the package

#3 - Subpackages

#4 - Package review
  • Packages are modules which can contain other modules.
  • Packages are generally implemented as directories containing a special __init__.py file.
  • The __init__.py file is executed when the package is imported.
  • Packages can contain subpackages which are themselves implemented as directories containing __init__.py files.
  • The module objects for packages have a __path__ attribute.

1.3 Relative imports
# an alternative form of imports called relative imports
from ..module_name import name
  • Note that you can only use relative imports with the “ from <module> import <names> ” form of import . Trying to do something like “ import .module ” is a syntax error.
  • Critically, relative imports can only be used within the current top-level package, never for importing modules outside of that package.

graphics/
    __init__.py
    primitives/
            __init__.py
            line.py
    shapes/
            __init__.py
            triangle.py
    scenes/
            __init__.py

triangle.py             module
.                                 graphics.shapes
..                                graphics
..primitives             graphics.shapes.primitives

#1 - Bare dots in the from clause
In relative imports it’s also legal for the from section to consist purely of dots. In this case the dots are still interpreted in exactly the same way as before.
Here the .. means “the parent of the current package”, just as with the first form of relative imports.

1.4 __all__
the optional __all__ attribute of modules. __all__ lets you control which attributes are imported when someone uses the from module import * syntax. If __all__ is not specified then from x import * imports all public 16 names from the imported module.
The __all__ module attribute must be a list of strings, and each string indicates a name which will be imported when the * syntax is used.

1.5 Namespace packages
Earlier we said that packages are implemented as directories containing a __init__.py file. This is true for most cases, but there are situations where you want to be able to split a package across multiple directories. This is useful, for example, when a logical package needs to be delivered in multiple parts, as happens in some of the larger Python projects.

Several approaches to addressing this need have been implemented, but it was in PEP420 in 2012 that an official solution was built into the Python language. This solution is known as namespace packages. A namespace package is a package which is spread over several directories, with each directory tree contributing to a single logical package from the programmer’s point of view.

Namespace packages are different from normal packages in that they don’t have __init__.py files. This is important because it means that namespace packages can’t have package level initialization code; nothing will be executed by the package when it’s imported. The reason for this limitation is primarily that it avoids complex questions of initialization order when multiple directories contribute to a package.
  • how does Python find them during import?
  • The answer is that Python follows a relatively simple algorithm to detect namespace packages.
  • When asked to import the name “foo”, Python scans each of the entries in sys.path in order.
    • If in any of these directories it finds a directory named “foo” containing __init__.py , then a normal package is imported.
    • If it doesn’t find any normal packages but it does find foo.py or any other file that can act as a module, then this module is imported instead.
    • Otherwise, the import mechanism keeps track of any directories it finds which are named “foo”. If no normal packages or modules are found which satisfy the import, then all of the matching directory names act as parts of a namespace package.

1.6 Executable directories
There are a number of ways to construct such programs, but one of the simplest is through the use of executable directories. Executable directories let you specify a main entry point which is run when the directory is executed by Python.

What do we mean when we say that Python “executes a directory”? We mean passing a directory name to Python on the command line like this:
$ mkdir text_stats
$ python3 text_stats

put a special module named __main__.py in the directory and Python will execute it. This module can execute whatever code it wants, meaning that it can call into modules you’ve created to provide, for example, a user interface to your modules.

#1 - __main__.py and sys.path

#2 - Zipping up executable directories
We can take the executable directory idea one step further by zipping the directory. Python knows how to read zip-files and treat them like directories, meaning that we can create executable zip-files just like we created executable directories.

Combining Python’s support for __main__.py with its ability to execute zip-files gives us a convenient way to distribute code in some cases. If you develop a program consisting of a directory containing some modules and a __main__.py , you can zip up the contents of the directory, share it with others, and they’ll be able to run it with no need for installing any packages to their Python installation.

1.7 Executable packages
put __main__.py in a package directory to make the package executable, then Python will execute it when you run the package
with python3 -m package_name

#1 - The difference between __init__.py and __main__.py
the package’s __init__.py is indeed executed when it’s imported, but, Python will not let us execute a package unless it contains __main__.py .

1.8 Recommended layout
Here’s the basic project layout:
project_name/
        setup.py
        project_name/
                __init__.py
                more_source.py
                subpackage1/
                        __init__.py
        test/
                test_code.py

1.9 Modules are singletons
If you find that you need a singleton in Python, one simple and effective way to implement it is as a module-level attribute. Since modules are only ever executed once, this guarantees that your singleton will only be initialized once. And since modules are initialized in a well-defined user-controlled order, you can have strong guarantees about when your singleton
will be initialized. This forms a strong basis for implementing practical singletons.

Consider a simple singleton registry, implemented in registry.py , where callers can leave their names:
# registry.py
_registry = []
def register(name):
        _registry.append(name)

def registered_names():
        return iter(_registry)

Callers would use it like this:
import registry
registry.register('my name')
for name in registry.registered_names():
        print(name)

The first time registry is imported, the _registry list is initialized. Then, every call to register and registered_names will access that list with complete assurance that it has been properly initialized.

Summary
  • Packages:
    • Packages are a special type of module
    • Unlike normal module, packages can contain other modules, including other packages.
    • Packages hierarchies are a powerful way to organize related code.
    • Packages have a __path__ member which is a sequence specifying the directories from which a package is loaded.
    • A simple standard project structure includes a location for non-python files, the project’s package, and a dedicated test subpackage.
  • sys.path :
    • sys.path is a list of directories where Python searches for modules.
    • sys.path is a normal list and can be modified and queried like any other list.
    • If you start Python with no arguments, an empty string is put at the front of sys.path . This instructs Python to import modules from the current directory.
    • Appending directories to sys.path at runtime allows modules to be imported from those directories.
  • PYTHONPATH :
    • PYTHONPATH is an environment variable containing a list of directories.
    • The format of PYTHONPATH is the same as for PATH on your system. It’s a semicolon-separated list on Windows and a colon-separated list on Linux or Mac OS X.
    • The contents of PYTHONPATH are added as entries to sys.path .
  • __init__.py :
    • Normal packages are implemented by putting a file named __init__.py into a directory.
    • The __init__.py file for a package is executed when the package is imported.
    • __init__.py files can hoist attributes from submodule into higher namespaces for convenience.
  • Relative imports:
    • Relative import allow you to import modules within a package without specifying the full module path.
    • Relative imports must use the from module import name form of import.
    • The “from” portion of a relative import starts with at least one dot.
    • Each dot in a relative import represents a containing package.
    • The first dot in a relative import means “the package containing this module.”
    • Relative imports can be useful for reducing typing.
    • Relative imports can improve modifiability in some cases.
    • In general, it’s best to avoid relative imports because they can make code harder to understand.
  • Namespace packages:
    • A namespace package is a package split across several directories.
    • Namespace packages are described in PEP420.
    • Namespace packages don’t use __init__.py files.
    • Namespace packages are created when one or more directories in the Python path match an import request and no normal packages or modules match the request.
    • Each directory that contributes to a namespace package is listed in the package’s __path__ attribute.
  • Executable directories:
    • Executable directories are created by putting a __main__.py file in a directory.
    • You execute a directory with Python by passing it to the Python executable on the command line.
    • When __main__.py is executed its __name__ attribute is set to __main__ .
    • When __main__.py is executed, it’s parent directory is automatically added to sys.path .
    • The if __name__ == '__main__': construct is redundant in a __main__.py file.
    • Executable directories can be compressed into zip-files which can be executed as well.
    • Executable directories and zip-files are convenient ways to distribute Python programs.
  • Modules:
    • Modules can be executed by passing them to Python with the -m argument.
    • The __all__ attribute of a module is a list of string specifying the names to export when from module import * is used.
    • Module-level attributes provide a good mechanism for implementing singletons.
    • Modules have well-defined initialization semantics.
  • Miscellaneous:
    • The standard gzip module allows you to work with files compressed using GZIP.
    • The standard bz2 module allows you to work with files compressed using BZ2.


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝


已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
经管之家编辑部 + 100 + 3 + 3 + 3 精彩帖子

总评分: 论坛币 + 100  学术水平 + 3  热心指数 + 3  信用等级 + 3   查看全部评分

本帖被以下文库推荐

沙发
经管之家编辑部 在职认证  发表于 2019-5-23 07:26:56
为您点赞!

藤椅
从1万到一亿 在职认证  发表于 2019-5-23 14:35:50

板凳
充实每一天 发表于 2019-5-23 14:43:44 来自手机
点赞

报纸
胡明敏 发表于 2019-5-23 20:18:23
谢谢分享

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
扫码
拉您进交流群
GMT+8, 2026-2-6 04:49