Skip to content

Files

Latest commit

03035da · Jan 9, 2022

History

History
448 lines (290 loc) · 16.1 KB

10.md

File metadata and controls

448 lines (290 loc) · 16.1 KB

十、模块

模块

Python 模块是扩展名为.py的文件。这些可以用来实现一组属性(变量)、方法(函数)和类(类型)。只需使用后跟模块名称的import语句,就可以在另一个 Python 程序中包含一个模块。要导入名为time的模块,请在 Python 程序中包含import time。您现在可以通过调用time.method_name()来访问time模块中的方法,或者通过调用time.attribute_name来访问属性,有时称为变量。下面的代码清单是一个使用asctime()方法和来自time模块的timezone属性的例子。timezone属性包括世界协调时和当地时间之间的秒数。

代码清单 263

            import time
            print(time.asctime())
            print(time.timezone)

输出:

代码清单 264

            Tue Aug 25 14:28:03 2015
            21600

无论何时import module_name,该模块中的所有方法都将作为module_name.method_name()可用。如果您选择在一个模块中使用单一方法,您可以使用from module_name import method_name语法导入该方法。现在这个方法可以在你的程序中通过名字来访问。不再叫module_name.method_name(),你现在可以简单的叫method_name()

代码清单 265

            from time import asctime
            print(asctime())

输出:

代码清单 266

            Tue Aug 25 14:28:03 2015

使用模块属性和类可以做同样的事情。如果您希望从一个模块中导入多个项目,您可以为每个项目创建单独的from module_name import method_name行。您也可以选择提供一个逗号分隔的列表,如:from module_name import method_name1, method_name2, method_nameN。让我们从time模块导入asctime()sleep()方法。sleep()方法暂停程序的执行一段指定的秒数。

代码清单 267

            from time import asctime, sleep
            print(asctime())
            sleep(5)
            print(asctime())

输出:

代码清单 268

            Tue Aug 25 14:28:03 2015
            Tue Aug 25 14:28:08 2015

从模块中导入单个方法或方法列表的主要好处之一是,您可以通过名称直接访问它,而不必在它前面加上模块名称。例如sleep(5)time.sleep(5)。如果您希望能够访问模块中的所有内容,您可以使用星号来代替方法列表进行导入。不过,这不是我推荐的做法。这里值得一提,只是因为你会看到它不时被使用。最好避免这种方法的主要原因是,如果将所有内容都导入到程序中,就会冒覆盖现有函数或变量的风险。此外,当您使用星号导入多个方法时,您会发现很难确定到底是什么从哪里来的。

代码清单 269

            from time import *
            print(timezone)
            print(asctime())
            sleep(5)
            print(asctime())

输出:

代码清单 270

            21600
            Tue Aug 25 14:28:03 2015
            Tue Aug 25 14:28:08 2015

窥视模块内部

您可以使用内置的dir()函数来发现任何一个模块中存在哪些属性、方法和类。

代码清单 271

            >>> import time
            >>> dir(time)
            ['_STRUCT_TM_ITEMS', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'clock', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'perf_counter', 'process_time', 'sleep', 'strftime', 'strptime', 'struct_time', 'time', 'timezone', 'tzname', 'tzset']

模块搜索路径

请记住,您总是可以通过检查sys.path来查看默认的模块搜索路径。每当您提供import module_name语句时,Python 都会在列表的第一个路径中查找该模块。如果 Python 找不到它,那么将检查下一个路径,以此类推。这将持续下去,直到找到该模块,或者直到所有模块搜索路径完全用尽。模块搜索路径可能包括 zip 文件以及目录。Python 也会在 zip 文件中搜索匹配的模块。需要注意的是,默认的模块搜索路径会因您安装的 Python、Python 版本和操作系统而异。下面的代码清单是一个在苹果电脑上安装 Python 的例子。

代码清单 272

            # show_module_path.py
            import sys
            for path in sys.path:
               print(path)

输出:

代码清单 273

            /Users/david
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python34.zip
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plat-darwin
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/lib-dynload
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages

当我第一次执行python3 show_module_path.pyshow_module_path.py文件位于/Users/david。注意/Users/david列在模块搜索路径的第一位。其他目录由 Python 安装决定。

如果您想让 Python 在其他位置搜索模块,您需要操作模块搜索路径。有两种方法可以做到这一点。第一种方法是像修改任何其他列表一样修改sys.path。例如,您可以使用字符串数据类型追加目录位置。

代码清单 274

            import sys
            sys.path.append('/Users/david/python')
            for path in sys.path:
               print(path)

输出:

代码清单 275

            /Users/david
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python34.zip
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plat-darwin
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/lib-dynload
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages
            /Users/david/python

您还可以操作PYTHONPATH环境变量。该变量的作用方式与PATH环境变量非常相似。在 Mac 和 Linux 系统上,PYTHONPATH可以用冒号分隔的目录列表填充。在 Windows 系统上,PYTHONPATH环境变量需要使用分号来分隔目录列表。在PYTHONPATH中列出的目录被插入脚本所在的目录之后,默认模块搜索路径之前。

在下面的例子中,/Users/davidshow_module_path.py Python 程序所在的目录。/Users/david/python/usr/local/python/modules路径包含在PYTHONPATH中。export命令使从外壳启动的程序可以使用PYTHONPATH

代码清单 276

            [david@mac ~]$ export PYTHONPATH=/Users/david/python:/usr/local/python/modules
            [david@mac ~]$ pwd
            /Users/david
            [david@mac ~]$ python3 show_module_path.py
            /Users/david
            /Users/david/python
            /usr/local/python/modules
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python34.zip
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/plat-darwin
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/lib-dynload
            /Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages
            [david@mac ~]$

如果在搜索路径中找不到模块,将会出现ImportError异常。

代码清单 277

            import say_hello

输出:

代码清单 278

            Traceback (most recent call last):
             File "test_say_hello.py", line 1, in <module>
               import say_hello
            ImportError: No module named 'say_hello'

Python 标准库

正如我们在前面的例子中所做的,我们一直在使用 Python 附带的时间模块。事实上,Python 提供了一个很大的模块库供您利用。我强烈建议您在考虑编写自己的代码之前,花点时间真正了解一下 Python 标准库能提供什么。例如,如果您希望读写 CSV(逗号分隔值)文件,不要浪费时间从头开始创建已经存在的东西。只需使用 Python 预先存在的csv模块。您是否希望在程序中启用登录?嗯,有一个logging模块可以帮助你做到这一点。您想向 web 服务发出 HTTP 请求,然后解析 JSON 响应吗?尝试使用urllib.requestjson模块。要了解这些模块和更多内容,请查看位于https://docs.python.org/3/library/的 Python 标准库的列表。

现在,让我们使用sys模块中的exit()方法,如果检测到错误,干净利落地终止您的程序。在下面的例子中,文件test.txt被打开。如果程序在打开文件时遇到错误,将执行except:后面的代码块。如果阅读test.txt是剩余代码正常运行的必要条件,则无需继续。exit()方法可以接受退出代码作为参数。如果未提供退出代码,将使用0。按照惯例,当错误导致程序退出时,需要非零退出代码。

代码清单 279

            import sys
            file_name = 'test.txt'
            try:
               with open(file_name) as test_file:
                  for line in test_file:
                      print(line)
            except:
               print('Could not open {}.'.format(file_name))
               sys.exit(1)

创建自己的模块

正如 Python 有自己的可重用代码库一样,您也可以。创建自己的模块非常简单。请记住,在最简单的形式中,模块是扩展名为.py的文件。只需用你的代码创建一个 Python 文件并从另一个 Python 程序中import它。

以下代码清单是say_hello.py的内容。

代码清单 280

            def say_hello():
               print('Hello!')

注意如何导入和使用say_hello模块。要调用say_hello模块中的say_hello()方法,请使用say_hello.say_hello()

代码清单 281

            import say_hello
            say_hello.say_hello()

输出:

代码清单 282

            Hello!

下面的例子是另一个叫做say_hello2的简单模块。以下代码是say_hello2.py的正文。

代码清单 283

            def say_hello():
               print('Hello!')

            print('Hello from say_hello2.py!')

让我们看看当你导入say_hello2模块时会发生什么。

代码清单 284

            import say_hello2
            say_hello2.say_hello()

输出:

代码清单 285

            Hello from say_hello2.py!
            Hello!

发生了什么?当say_hello2被导入时,它的内容被执行。首先,定义say_hello()功能。从那里执行print功能。通过这种方式,Python 使您能够创建在执行时以一种方式运行的程序,以及在导入时以另一种方式运行的程序。如果您希望能够重用现有 Python 程序中的函数,但不想执行主程序,您可以考虑这一点。

使用

每当 Python 文件作为程序执行时,特殊变量__name__将被设置为__main__。请注意,这些特殊变量的名称两边各有两个下划线字符。在导入的情况下,__name__变量将不被填充。最终,您可以使用它来控制 Python 程序的行为。以下代码示例是say_hello3.py文件。

代码清单 286

            def say_hello():
               print('Hello!')

            def main():
               print('Hello from say_hello3.py!')
               say_hello()

            if __name__ == '__main__':
               main()

无论何时作为程序执行,都会执行if __name__ == '__main__'之后的代码块。在下面的例子中,它简单地称为main()。这是一种非常常见的模式,您将在许多 Python 应用程序中看到这一点。当say_hello3.py作为模块导入时,除非从导入程序中明确调用,否则不会执行任何操作。

代码清单 287

            [david@mac ~]$ python3 say_hello3.py
            Hello from say_hello3.py!
            Hello!
            [david@mac ~]$

审核

Python 模块是扩展名为. py 的文件,能够实现一组变量、函数和类。

使用import module_name语法导入模块。

默认模块搜索路径将由您的 Python 安装决定。

要操作模块搜索路径,修改sys.path或设置PYTHONPATH环境变量。

Python 标准库是一个相当大的代码集合,可以在您的 Python 程序中重用。

使用dir()内置功能,找出模块中存在的确切内容。

您可以通过编写自己的模块来建立自己的个人库。

通过检查___name___的值,您可以根据 Python 程序是交互运行还是导入来影响其行为。

if __name__ == '__main__':语法是一个常见的 Python 习语。

练习

猪说话,热毒

更新我们在第 1 章讨论的“猪语”程序,使其可以作为模块导入或直接运行。当作为一个程序运行时,它应该提示输入,并显示一只猪“说”用户提供了什么。将用户提供的输入放入语音气泡中。这个语音气泡可以扩展或收缩,以适应用户提供的输入。

下面的代码清单显示了交互运行时的示例输出。

代码清单 288

                         ______________________
                       < Pet me and I will oink >
                         ----------------------
                       /
                ^..^ /
            ~( ( oo )
             ,, ,,

从这里,创建一个名为pig_talk.py的新程序,导入pig_say模块。尝试使用pig_say()模块中的功能向屏幕显示各种信息。

下面的代码清单显示了作为模块使用时的示例输出。

代码清单 289

                         ________
                       < Feed me. >
                         --------
                       /
                ^..^ /
            ~( ( oo )
             ,, ,,
                         ____________
                       < Oink. Oink. >
                         ------------
                       /
                ^..^ /
            ~( ( oo )
             ,, ,,

解决办法

以下代码是pig_say.py的内容。

代码清单 290

            def pig_say(text):
               """Generate a picture of a pig saying something"""
               text_length = len(text)
               print('             {}'.format('_' * text_length))
               print('           < {} >'.format(text))
               print('             {}'.format('-' * text_length))
               print('           /')
               print('    ^..^ /')
               print('~( ( oo )')
               print(' ,, ,,')

            def main():
               text = input('What would you like the pig to say? ')
               pig_say(text)

            if __name__ == '__main__':
               main()

以下代码是pig_talk.py的内容。

代码清单 291

            import pig_say

            def main():
               pig_say.pig_say('Feed me.')
               pig_say.pig_say('Oink. Oink.')

            if __name__ == '__main__':
               main()

资源

__main__文件:https://docs.python.org/3/library/main.html

Python 中的习语和反习语:https://docs.python.org/3.1/howto/doanddont.html

新手 Linux:http://www.linuxtrainingacademy.com/linux

PYTHONPATH文档:https://docs . python . org/3/using/cmdline . html # env var-PYTHONPATH

Python 标准库:https://docs.python.org/3/library/

sys模块:https://docs.python.org/3/library/sys.html

sys.path文件:https://docs.python.org/3/library/sys.html#sys.path

virtualenv文件:https://pypi . python . org/pypi/virtualenv