- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章构建Python包的五个简单准则简介由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
创建一个软件包(package)似乎已经足够简单了,也就是在文件目录下搜集一些模块,再加上一个__init__.py文件,对吧?我们很容易看出来,随着时间的推移,通过对软件包的越来越多的修改,一个设计很差的软件包可能会出现循环依赖问题,或是可能变得不可移植和不可靠。 1. __init__.py 仅为导入服务 。
对于一个简单的软件包,你可能会忍不住把工具方法,工厂方法和异常处理都丢进__init__.py,千万别这样! 。
一个结构良好的__init__.py文件,仅为一个非常重要的目的来服务:从子模块导入。你的__init__.py应该看起来像这个样子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# ORDER MATTERS HERE -- SOME MODULES ARE DEPENDANT ON OTHERS
# 导入顺序要考虑——一些模块会依赖另外的一些
from
exceptions
import
FSQError, FSQEnvError, FSQEncodeError,
FSQTimeFmtError, FSQMalformedEntryError,
FSQCoerceError, FSQEnqueueError, FSQConfigError,
FSQPathError, FSQInstallError, FSQCannotLockError,
FSQWorkItemError, FSQTTLExpiredError,
FSQMaxTriesError, FSQScanError, FSQDownError,
FSQDoneError, FSQFailError, FSQTriggerPullError,
FSQHostsError, FSQReenqueueError, FSQPushError
# constants relies on: exceptions, internal
import
constants
# const relies on: constants, exceptions, internal
from
const
import
const, set_const
# has tests
# path relies on: exceptions, constants, internal
import
path
# has tests
# lists relies on: path
from
lists
import
hosts, queues
#...
|
2.使用__init__.py来限制导入顺序 。
使用得当的话,__init__.py 可以为你提供重新组织内部软件包结构的灵活性,而不需要担心由内部导入子模块或是每个模块导入顺序所带来的副作用。因为你是以一个特定的顺序导入子模块,你的__init__.py 对于他程序员来讲应该简单易懂,并且能够明显的表示该软件包所能提供的全部功能.
文档字符串,以及在软件包层面对__all__属性的赋值应当是__init__.py中唯一的与导入模块不相关的代码:
1
2
3
4
5
6
7
8
9
10
|
__all__
=
[
'FSQError'
,
'FSQEnvError'
,
'FSQEncodeError'
,
'FSQTimeFmtError'
,
'FSQMalformedEntryError'
,
'FSQCoerceError'
,
'FSQEnqueueError'
,
'FSQConfigError'
,
'FSQCannotLock'
,
'FSQWorkItemError'
,
'FSQTTLExpiredError'
,
'FSQMaxTriesError'
,
'FSQScanError'
,
'FSQDownError'
,
'FSQDoneError'
,
'FSQFailError'
,
'FSQInstallError'
,
'FSQTriggerPullError'
,
'FSQCannotLockError'
,
'FSQPathError'
,
'path'
,
'constants'
,
'const'
,
'set_const'
,
'down'
,
'up'
,
# ...
]
|
3.使用一个模块来定义所有的异常 。
你也许已经注意到了,__init__.py中的第一个导入语句从exceptions.py子模块中导入了全部的异常。从这里出发,你将看到,在大多数的软件包中,异常被定义在引起它们的代码附近。尽管这样可以为一个模块提供高度的完整性,一个足够复杂的软件包会通过如下两种方式,使得这一模式出现问题.
通常一个模块/程序需要从一个子模块导入一个函数, 利用它导入代码并抛出异常。为了捕获异常并保持一定的粒度,你需要导入你需要的模块,以及定义了异常的模块(或者更糟,你要导入一系列的异常)。这一系列衍生出来的导入需求,是在你的软件包中编织一张错综复杂的导入之网的始作俑者。你使用这种方式的次数越多,你的软件包内部就变的越相互依赖,也更加容易出错。 随着异常数量的不断增长,找到一个软件包可能引发的全部异常变的越来越难。把所有的异常定义在一个单独的模块中,提供了一个方便的地方,在这里,程序员可以审查并确定你的软件包所能引发全部潜在错误状态.
你应该为你的软件包的异常定义一个基类
1
2
3
4
|
class
APackageException(Exception):
'''root for APackage Exceptions, only used to except any APackage error, never raised'''
pass
|
然后确保你的软件包在任何错误状态下,只会引发这个基类异常的子类异常,这样如果你需要的话,你就可以阻止全部的异常:
1
2
3
4
5
6
|
try
:
'''bunch of code from your package'''
except
APackageException:
'''blanked condition to handle all errors from your package'''
|
对于一般的错误状态,这里有一些重要的异常处理已经被包括在标准库中了(例如,TypeError, ValueError等) 。
灵活地定义异常处理并保持足够的粒度:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# from fsq
class
FSQEnvError(FSQError):
'''An error if something cannot be loaded from env, or env has an invalid
value'''
pass
class
FSQEncodeError(FSQError):
'''An error occured while encoding or decoding an argument'''
pass
# ... and 20 or so more
|
在你的异常处理中保持更大的粒度,有利于让程序员们在一个try/except中包含越来越大的,互相不干涉的代码段.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# this
try
:
item
=
fsq.senqueue(
'queue'
,
'str'
,
'arg'
,
'arg'
)
scanner
=
fsq.scan(
'queue'
)
except
FSQScanError:
'''do something'''
except
FSQEnqueueError:
'''do something else'''
# not this
try
:
item
=
fsq.senqueue(
'queue'
,
'str'
,
'arg'
,
'arg'
)
except
FSQEnqueueError:
'''do something else'''
try
:
scanner
=
fsq.scan(
'queue'
)
except
FSQScanError:
'''do something'''
# and definitely not
try
:
item
=
fsq.senqueue(
'queue'
,
'str'
,
'arg'
,
'arg'
)
try
:
scanner
=
fsq.scan(
'queue'
)
except
FSQScanError:
'''do something'''
except
FSQEnqueueError:
'''do something else'''
|
在异常定义时保持高度的粒度,会减少错综复杂的错误处理,并且允许你把正常执行指令和错误处理指令分别开来,使你的代码更加易懂和更易维护。 4. 在软件包内部只进行相对导入 。
在子模块中你时常见到的一个简单错误,就是使用软件包的名字来导入软件包.
1
2
|
# within a sub-module
from
a_package
import
APackageError
|
这样做会导致两个不好的结果:
尽管第一条看上去并不是什么大问题,但是考虑一下,如果你在 PYTHONPATH 下的两个目录中,有两个同名的软件包。你的子模块可能最终导入了另一个软件包,你将无意间使得某个或某些对此毫无戒备的程序员(或是你自己)debug 到深夜。 。
1
2
3
4
5
6
7
|
# within a sub-module
from
.
import
FSQEnqueueError, FSQCoerceError, FSQError, FSQReenqueueError,
constants as _c, path as fsq_path, construct,
hosts as fsq_hosts, FSQWorkItem
from
.internal
import
rationalize_file, wrap_io_os_err, fmt_time,
coerce_unicode, uid_gid
# you can also use ../... etc. in sub-packages.
|
5. 让模块保持较小的规模 。
你的模块应当比较小。记住,那个使用你软件包的程序员会在软件包作用域进行导入,同时你会使用你的 __init__.py 文件来作为一个组织工具,来暴露一个完整的接口.
好的做法是一个模块只定义一个类,伴随一些帮助方法和工厂方法来协助建立这个模块.
1
2
3
4
5
6
7
|
class
APackageClass(
object
):
'''One class'''
def
apackage_builder(how_many):
for
i
in
range
(how_many):
yield
APackageClass()
|
如果你的模块暴露了一些方法,把一些相互依赖的方法分为一组放进一个模块,并且把不相互依赖的方法移动到单独的模块中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
####### EXPOSED METHODS #######
def
enqueue(trg_queue, item_f,
*
args,
*
*
kwargs):
'''Enqueue the contents of a file, or file-like object, file-descriptor or
the contents of a file at an address (e.g. '/my/file') queue with
arbitrary arguments, enqueue is to venqueue what printf is to vprintf
'''
return
venqueue(trg_queue, item_f, args,
*
*
kwargs)
def
senqueue(trg_queue, item_s,
*
args,
*
*
kwargs):
'''Enqueue a string, or string-like object to queue with arbitrary
arguments, senqueue is to enqueue what sprintf is to printf, senqueue
is to vsenqueue what sprintf is to vsprintf.
'''
return
vsenqueue(trg_queue, item_s, args,
*
*
kwargs)
def
venqueue(trg_queue, item_f, args, user
=
None
, group
=
None
, mode
=
None
):
'''Enqueue the contents of a file, or file-like object, file-descriptor or
the contents of a file at an address (e.g. '/my/file') queue with
an argument list, venqueue is to enqueue what vprintf is to printf
if entropy is passed in, failure on duplicates is raised to the caller,
if entropy is not passed in, venqueue will increment entropy until it
can create the queue item.
'''
# setup defaults
trg_fd
=
name
=
None
# ...
|
上面的例子是 fsq/enqueue.py,它暴露了一系列的方法来为同一个功能提供不同的接口(就像 simplejson 中的l oad/loads)。尽管这个例子足够直观,让你的模块保持较小规模需要一些判断,但是一个好的原则是:
当你有疑问的时候,就去创建一个新的子模块吧.
最后此篇关于构建Python包的五个简单准则简介的文章就讲到这里了,如果你想了解更多关于构建Python包的五个简单准则简介的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, over
我开始自学数据库的基础知识,目前正在研究1.到3.普通形式。到目前为止,我了解的是希望消除冗余,以使我的数据库在数据更改阶段不太容易出现不一致的情况,并希望通过消除尽可能多的重复项来节省空间。 例如,
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
我有 2 个自动续订的应用程序内订阅正在接受 Apple 审核,但我一直被拒绝。请注意,这与 IAP 产品(显然尚未审查)无关,而是与我在 UI 中呈现信息的方式有关。我永远无法让 Apple 明确说
我非常喜欢 Entity Framework Code First 的想法,因为我可以快速制作新项目的原型(prototype),但现在我正在处理一个已经存在的数据库。 我们有许多具有相同模式的数据库
关于网页上的链接颜色与常规文本之间的对比,是否有任何最佳做法或指南? 我知道有关于文本与背景颜色的对比度指南,但我也想知道是否有关于纯文本和链接文本之间应存在的最小颜色差异的指南。 例如,我的背景是白
这是我的应用程序第二次因 GPS 后台 key 而被拒绝。这是我正在使用的代码: -(void)stopGPS{ [self.locationManagerAll stopUpdatingLocati
是否有一个Python模块,当给定两个向量x和y,其中y是二类(0,1)时,它计算Fisher准则,如这里的公式http://compbio.soe.ucsc.edu/genex/genexTR2ht
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 4 年前。 Improv
我们正在实现一个 Windows 7 应用程序,它会在任务栏的通知区域中显示一个弹出窗口。 简单形式有两个版本。 和精简版: 哪个更接近 Windows 的 UI 指南?有充分的理由偏爱其中之一吗?
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 5年前关闭。 Improve t
我使用带有随机初始化的 k 均值聚类来进行聚类识别。算法适用于良好的数据。但是,如果我处理带有很多噪声的数据,那么我的 k-means 算法就会失去其稳健性,并且会为同一数据集上的每次运行提供不同的解
我正在尝试使用 pygame 在一个简单的 2D 窗口中模拟重力。这是非常简单的东西(一个点再次上升和下降),我理解其中的机制,即速度作为向量,并且 y 部分在每次主循环运行以及随后的位置更新期间不断
我们开发了一款约会应用,要求用户输入高度等个人信息。我们的应用程序获得批准超过 5 次,但最近因更新而被拒绝。我们需要这些信息,因为我们希望每个配置文件都保持一致,而不是有任何半填充的配置文件。我们还
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 10 个月前。 Impro
我在 Django 中有一个类似这样的长 url 模式: url(r'^(?i)top-dir/(?P[-\w]+?)/(?P[-\w]+?)/(?P[-\w]+?).html/$', 'ap
我使用 Firebase 进行用户身份验证,我刚刚重新提交了我的应用程序并得到了以下拒绝: Guideline 5.1.2 - Legal - Privacy - Data Use and Shari
Google AdMob 现在显示以下警告。 为 iOS 14 准备您的应用程序 Apple 宣布了新的 AppTrackingTransparency 框架,该框架需要对您的 iOS 应用程序进行更
我是一名优秀的程序员,十分优秀!