12.模块
一、实验目的
- 解释器
- 模块的导入
- 包
- 默认/第三方模块介绍
- 命令行参数
二、知识要点
1.解释器
在实验1
中我们解释了在linux
系统下解释器的使用,在本文中我想通过学习Win32
系统中解释器来进行复习。Python的编程模式分为两种:交互式
,脚本式
,我们可以通过Win+R
在运行框中输入cmd
来启动命令提示符,当我们配置好Python环境时在命令提示符中输入python
并按下enter
此时即可启动Python的解释器,如图所示:
在这个窗口中输入python语句就可以直接得到运行的结果,这就是交互式编程。而我们通过记事本或者其他文本编辑器事先在文档中输入Python语句并保存为.py
文件,通过命令提示符调用该文件模式成为脚本式,例如,我在路径:D:\\python
中保存了一个名为hello.py
的脚本文件,通过:
可以发现Python解释器输出了脚本的内容。
2.模块
当我们退出解释器再进入时,我们定义的所有方法和变量就全部消失了,为此Python提供了一个方法,把这些定义存放在文件中,为一些脚本或者交互式的解释器实例使用,这个文件就称之为模块
。
模块是一个包含了所有我们定义的函数和变量的文件,其后缀名为.py
。模块可以被别的程序引入,以使用该模块中的函数等功能,这也是使用Python标准库的方法。
import sys
print('命令行参数如下:')
for i in sys.argv:
print(i)
print('\n\nPython路径为:', sys.path, '\n')
我们通过命令提示符输入:
python module.py 1 2
输出为:
命令行参数如下:
module.py
1
2
Python路径为: ['F:\\Python\\12', 'C:\\Users\\zzzzh\\AppData\\Local\\Programs\\Python\\Python38\\python38.zip', 'C:\\Users\\zzzzh\\AppDa
ta\\Local\\Programs\\Python\\Python38\\DLLs', 'C:\\Users\\zzzzh\\AppData\\Local\\Programs\\Python\\Python38\\lib', 'C:\\Users\\zzzzh\\Ap
pData\\Local\\Programs\\Python\\Python38', 'F:\\Python\\venv', 'F:\\Python\\venv\\lib\\site-packages', 'F:\\Python\\venv\\lib\\site-pack
ages\\setuptools-40.8.0-py3.8.egg', 'F:\\Python\\venv\\lib\\site-packages\\pip-19.0.3-py3.8.egg']
其中:
-
import sys
引入 python 标准库中的sys.py
模块;这是引入某一模块的方法。 -
sys.argv
是一个包含命令行参数的列表。 -
sys.path
包含了一个 Python 解释器自动查找所需模块的路径的列表。
2.1 import
想使用 Python 源文件,只需在另一个源文件里执行 import 语句,语法如下:
import module1[, module2[,... moduleN]
当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入。搜索路径是一个解释器会先进行搜索的所有目录的列表。例如我们创建一个print_f
模块:
def print_f( par ):
print ("Hello : ", par)
return
将上述文件保存为print_f.py
,在同一目录创建新脚本test.py
,在脚本中输入:
# 导入模块
import print_f
# 调用模块中的函数
print_f.print_f("hello")
运行会输出:
Hello : hello
一个模块只会被导入一次,不管你执行了多少次import
,这样可以防止导入的模块被多次执行,当我们使用import
语句时,Python解释器就在他所具有的搜索路径中搜索模块,搜索路径是由一系列目录名构成的,也可以通过定义环境变量的方式来确定搜索路径。搜索路径存储在sys.path
变量中:
import sys
print(sys.path)
我们会得到:
['F:\\Python\\12', 'F:\\Python', 'C:\\Users\\zzzzh\\AppData\\Local\\Programs\\Python\\Python38\\python38.zip', 'C:\\Users\\zzzzh\\AppData\\Local\\Programs\\Python\\Python38\\DLLs', 'C:\\Users\\zzzzh\\AppData\\Local\\Programs\\Python\\Python38\\lib', 'C:\\Users\\zzzzh\\AppData\\Local\\Programs\\Python\\Python38', 'F:\\Python\\venv', 'F:\\Python\\venv\\lib\\site-packages', 'F:\\Python\\venv\\lib\\site-packages\\setuptools-40.8.0-py3.8.egg', 'F:\\Python\\venv\\lib\\site-packages\\pip-19.0.3-py3.8.egg']
我们可以发现,sys.path
输出是一个列表,其中第一项是当前目录,通过了解了搜索路径的概念,我们就可以在脚本中修改sys.path
来引入一些不在搜索路径中的模块。有关跨目录搜索的问题我将会在另外的文章中详细解释。
2.2 import……from
语句
Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中,语法如下:
from modname import name1[, name2[, ... nameN]]
我们创建一个名为Tmodule.py
的模块,在其中写入如下代码:
def module_1(var):
print("模块一已调用", var)
def module_2(var):
print("模块二已调用", var)
在同一目录创建test.py
,在test.py
脚本中输入:
from Tmodule import module_1
module_1(1)
module_2(1)
运行结果为:
模块一已调用 1
Traceback (most recent call last):
File "F:/Python/12/test.py", line 8, in <module>
module_2(1)
NameError: name 'module_2' is not defined
可以发现,通过from……import
语句,引入了Tmodule
模块中的module_1
函数而未引入module_2
函数。
我们可以通过from modname import *
来导入一个模块中的所有项目,但是这种声明不该被过多的使用,这是因为,模块除了方法定义,还可以包括可执行的代码。这些代码一般用于初始化这个模块,这些代码只有在第一次导入时才会被执行,每个模块有鸽子独立的符号表,在模块内部为所有的函数作为全局符号表来使用,当你将已有的模块导入你的项目时,被导入的模块的名称将被放入当前操作的项目符号表中,而如果已有模块中与你的项目中的命名、定义相同,就会产生覆盖问题。
2.3 __name__
属性
一个模块被另一个程序第一次引入时,其主程序将运行,而如果我们想在模块被引入的时候模块中的某一程序块不执行,我们可以使用__name__
属性来使该程序块仅在该模块自身运行时运行,例如我们在目录下创建name.py
,在其中输入:
if __name__ == '__main__':
print("我正在运行")
else:
print("我来自其他模块")
我们执行该脚本,会输出我正在运行
,如果我们在另一脚本中调用该模块:import name
会输出我来自其他模块
2.4 dir()
函数
内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:
例如我们在test.py
中引入上文创建的所有脚本:
import name
import module
import Tmodule
import Delimiter
print(dir(name))
print(dir(module))
print(dir(Tmodule))
print(dir(Delimiter))
在运行的时候会输出:
*
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'i', 'sys']
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'module_1', 'module_2']
['Less_d', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'mult_d', 'plus_d']
*
的内容为调用模块执行的程序
dir()
函数不仅仅能显示用户自定义模块中的名称,只要是一个模块,dir()
函数都可显示。
拓展:标准模块
Python本身带着一些标准的模块库,其中有些模块被直接构建在解析器里,这些虽然不是一些语言内置的功能,但是他却能很高效的使用,甚至是系统级调用也没问题。这些组件会根据不同的操作系统进行不同形式的配置,比如 winreg 这个模块就只会提供给 Windows 系统。应该注意到这有一个特别的模块 sys ,它内置在每一个 Python 解析器中。我们可以在Python的解释器中输入:
>>> help()
Welcome to Python 3.8's help utility!
If this is your first time using Python, you should definitely check out
the tutorial on the Internet at https://docs.python.org/3.8/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
To get a list of available modules, keywords, symbols, or topics, type
"modules", "keywords", "symbols", or "topics". Each module also comes
with a one-line summary of what it does; to list the modules whose name
or summary contain a given string such as "spam", type "modules spam".
help> modules
Please wait a moment while I gather a list of all available modules...
Delimiter _tkinter glob searchpath
Tmodule _tracemalloc gzip secrets
__future__ _warnings hashlib select
_abc _weakref heapq selectors
_ast _weakrefset hmac setuptools
_asyncio _winapi html shelve
_bisect _xxsubinterpreters http shlex
_blake2 abc idlelib shutil
_bootlocale aifc imaplib signal
_bz2 antigravity imghdr site
_codecs argparse imp smtpd
_codecs_cn array importlib smtplib
_codecs_hk ast inspect sndhdr
_codecs_iso2022 asynchat io socket
_codecs_jp asyncio ipaddress socketserver
_codecs_kr asyncore itertools sqlite3
_codecs_tw atexit json sre_compile
_collections audioop keyword sre_constants
_collections_abc base64 lib2to3 sre_parse
_compat_pickle bdb linecache ssl
_compression binascii locale stat
_contextvars binhex logging statistics
_csv bisect lzma string
_ctypes builtins mailbox stringprep
_ctypes_test bz2 mailcap struct
_datetime cProfile marshal subprocess
_decimal calendar math sunau
_dummy_thread cgi mimetypes symbol
_elementtree cgitb mmap symtable
_functools chunk module sys
_hashlib cmath modulefinder sysconfig
_heapq cmd msilib tabnanny
_imp code msvcrt tarfile
_io codecs multiprocessing telnetlib
_json codeop name tempfile
_locale collections netrc test
_lsprof colorsys nntplib testmodule
_lzma compileall nt textwrap
_markupbase concurrent ntpath this
_md5 configparser nturl2path threading
_msi contextlib numbers time
_multibytecodec contextvars opcode timeit
_multiprocessing copy operator tkinter
_opcode copyreg optparse token
_operator crypt os tokenize
_osx_support csv parser trace
_overlapped ctypes pathlib traceback
_pickle curses pdb tracemalloc
_py_abc dataclasses pickle tty
_pydecimal datetime pickletools turtle
_pyio dbm pip turtledemo
_queue decimal pipes types
_random difflib pkg_resources typing
_sha1 dis pkgutil unicodedata
_sha256 distutils platform unittest
_sha3 doctest plistlib urllib
_sha512 dummy_threading poplib uu
_signal easy_install posixpath uuid
_sitebuiltins email pprint venv
_socket encodings print_f warnings
_sqlite3 ensurepip profile wave
_sre enum pstats weakref
_ssl errno pty webbrowser
_stat faulthandler py_compile winreg
_statistics filecmp pyclbr winsound
_string fileinput pydoc wsgiref
_strptime fnmatch pydoc_data xdrlib
_struct formatter pyexpat xml
_symtable fractions queue xmlrpc
_testbuffer ftplib quopri xxsubtype
_testcapi functools random zipapp
_testconsole gc re zipfile
_testimportmultiple genericpath reprlib zipimport
_testmultiphase getopt rlcompleter zlib
_thread getpass runpy
_threading_local gettext sched
Enter any module name to get more help. Or, type "modules spam" to search
for modules whose name or summary contain the string "spam".
我们通过help(str)
可以得到字符串所有可用方法,其他内容类似。较为常用的模块与第三方模块我将在其他文章中写入。
3.包
包是一种管理 Python 模块命名空间的形式,采用"点模块名称"。他能有效的避免不同库之间的模块重名的情况,如下图的目录中:
目录只有包含一个叫做
__init__.py
的文件才会被认作是一个包,最简单的情况,放一个空的文件__init__.py
就可以了。用户可以每次只导入一个包里面的特定模块,比如:
import people.type.color
这将会导入子模块:people.type.color
。 他必须使用全名去访问:
people.type.color.eye(input, output)
还有一种导入子模块的方法是:
from people.type import color
这同样会导入子模块: color
,并且他不需要那些冗长的前缀,所以他可以这样使用:
color.eye(input,output)
还有一种变化就是直接导入一个函数或者变量:
from people.type.color import eye
同样的,这种方法会导入子模块: color
,并且可以直接使用他的 eye()
函数:
eye(input,output)
如果我们使用from people.type import *
,Python 会进入文件系统,找到这个包里面所有的子模块,一个一个的把它们都导入进来。但是在Windows系统中这种方法可能会出现问题,因为Windows是一个不区分大小写的系统,因此,通常在目录中的__init__.py
文件中会存在一个名为__all__
的列表变量,比如在people/type/__init__.py
文件中包含代码:
__all__ = ["color", "like"]
这表示当我们使用from people.type import *
这种用法时,只会导入包里面的这两个子模块,如果__all__
没有定义,则使用from people.type import *
时不会导入包people.type
中的任何子模块,他只是把包people.type
和她里面定义的所有内容导入进来。并且他不会破坏掉我们在这句话之前导入的所有明确指定的模块。
无论是隐式的还是显式的相对导入都是从当前模块开始的。主模块的名字永远是"__main__"
,一个Python应用程序的主模块,应当总是使用绝对路径引用。包还提供一个额外的属性__path__
。这是一个目录列表,里面每一个包含的目录都有为这个包服务的__init__.py
,你得在其他__init__.py
被执行前定义。可以修改这个变量,用来影响包含在包里面的模块和子包。这个功能并不常用,一般用来扩展包里面的模块。
三、实验内容
1.分隔符
写一个模块用于输出至少三种分隔符,调用包中的函数,参数输入数字,打印该数量的分割符,分隔符可以包括*
,-
,+
- 代码:
# ""
# Delimiter Modules
# ============
# ""
def plus_d(num):
print("+"*num)
def Less_d(num):
print("-"*num)
def mult_d(num):
print("*"*num)
- 结果:
我们通过在解释器或者其他脚本中输入:
import Delimiter
Delimiter.plus_d(10)
Delimiter.Less_d(10)
Delimiter.mult_d(10)
输出为:
++++++++++
----------
**********
四、实验结果
1.下载文件程序
首先我们需要安装第三方库requests模块
,具体流程如下:
- 在Python图标上单击右键找到属性,单击打开文件位置。拷贝②中的路径(如果第一次查看文件位置是快捷方式可以重复本操作)
- 运行命令提示符,在命令提示符中输入:
cd 你拷贝的路径
,回车之后再输入cd Scripts
并按下回车切换至pip
文件目录,pip
是用于安装第三方模块的。
- 继续输入
pip3 install requests
,此时将会下载安装requests
模块
- 安装成功后可以在Python解释器中输入
dir(requests)
得到该模块中的名称。
当我们进行到这一步,在命令提示符中输入import requests
已经可以运行了,但是在Pycharm
中却缺少该库,我们可以通过File->Settings
:
然后,在
Project Interpreter
中找到+
并点击:Project Interpreter
搜索
requests
并安装:Requests
安装完成之后即可在
Pycharm
中使用。
- 代码:
import requests
def download(url):
'''
从指定的 URL 中下载文件并存储到当前目录
url: 要下载页面内容的网址
'''
# 检查 URL 是否存在
try:
req = requests.get(url)
except requests.exceptions.MissingSchema:
print('Invalid URL "{}"'.format(url))
return
# 检查是否成功访问了该网站
if req.status_code == 403:
print('You do not have the authority to access this page.')
return
filename = url.split('/')[-1]
with open(filename, 'w') as fobj:
fobj.write(req.content.decode('utf-8'))
print("Download over.")
if __name__ == '__main__':
url = input('Enter a URL: ')
download(url)
- 结果:
Enter a URL: https://codeload.github.com/iissnan/hexo-theme-next/zip/v5.1.4
敲击回车文件开始下载。