当前位置: 首页 > 后端技术 > Python

[Python]Python模块基础

时间:2023-03-25 21:17:33 Python

一、模块模块可以看成是函数的集合。一个py文件里面可以放一堆函数,所以一个py文件可以看成一个模块。如果这个py文件的文件名为module.py,则模块名为module。1、四种形式的模块在Python中,一共有以下四种形式的模块:自定义模块:如果自己写一个py文件,在文件里面写一堆函数,就叫做自定义模块。即用python编写的.py文件第三方模块:已编译成共享库或DLL的C或C++扩展,例如requests内置模块:用C编写并链接到python解释器的内置模块,比如时间包(文件夹):一个文件夹,把一系列模块组织在一起(注:文件夹下有一个__init__.py文件,称为包)2、为什么要用模块?使用第三方或内置模块是一种借用,可以大大提高开发效率。自定义模块将我们自己程序中使用的公共函数写成一个python文件,然后程序的各个组件都可以通过import来引用自定义模块的函数。2、如何使用模块一般我们使用import和from...import...来导入模块。下面以spam.py中的文件代码为例。#spam.pyprint('fromthespam.py')money=1000defread1():print('spammodule:',money)defread2():print('spammodule')read1()defchange():globalmoneymoney=01导入模块名语法如下:importmodule1[,module2[,...moduleN]导入导入的模块,访问需要加前缀。import第一次导入模块时会发生3件事:基于模块创建模块命名空间执行模块对应的文件,将执行过程中产生的所有名字都扔到模块命名空间中获取当前执行中的一个模块名称file注意:模块的重复导入会直接引用之前创建的结果,不会重复执行模块文件。#run.pyimportspam#fromthespam.pyimportspammoney=111111spam.read1()#'spammodule:1000'spam.change()print(spam.money)#0print(money)#111111importheavy命名:smt变量指向span模块的命名空间#run.pyimportspamassmmoney=111111sm.moneysm.read1()#'spammodule:1000'sm.read2sm.change()print(money)#1000导入多个模块importspam,time,os#推荐使用以下方法importspamimporttimeimportos2,frommodulenameimport具体函数语法如下:frommodnameimportname1[,name2[,...nameN]]该语句不会将整个模块导入到当前命名空间中,它只会导入模块中的一个或多个函数。From...import...导入的模块,访问不需要加前缀。from...import...第一次导入模块时发生了三件事:基于模块创建模块命名空间来执行模块对应的文件,并将执行过程中产生的名称全部扔到模块中namespaceforcurrentexecution在文件的命名空间中获取一个名称,它直接指向模块中的某个名称,这意味着你可以直接使用它而无需添加任何前缀。#run.pyfromspamimportmoneyfromspamimportmoney,read1money=10print(money)#10rom...import*语句:导入文件中的所有函数:#spam.py__all__=['money','read1']#只允许导入'money'和'read1'#run.pyfromspamimport*#导入spam.py中的所有函数,但仅限于__all__money=111111read1()#'spammodule:1000'change()read1()#'spammodule:0'print(money)#1111113.在以下情况下会发生循环导入:#m1.pyprint('fromm1.py')fromm2importxy='m1'#m2.pyprint('fromm2.py')fromm1importyx='m2'可以利用函数定义阶段只识别语法的特性来解决循环导入的问题,或者从本质上解决循环导入的问题,但最好的解决方案是不要循环导入。解决方案1:#m1.pyprint('fromm1.py')deffunc1():fromm2importxprint(x)y='m1'#m2.pyprint('fromm2.py')deffunc1():fromm1importyprint(y)x='m2'方案二:5,#m1.pyprint('fromm1.py')y='m1'fromm2importx#m2.pyprint('fromm2.py')x='m2'fromm1importy4,dir()函数内置函数dir()可以找到模块中定义的所有名称。以一个字符串列表的形式返回:dir(sys)['__displayhook__','__doc__','__excepthook__','__loader__','__name__','__package__','__stderr__','__stdin__','__stdout__','_clear_type_cache'、'_current_frames'、'_debugmallocstats'、'_getframe'、'_home'、'_mercurial'、'_xoptions'、'abiflags'、'api_version'、'argv'、'base_exec_prefix'、'base_prefix'、'builtin_module_names','byteorder','call_tracing','callstats','copyright','displayhook','dont_write_bytecode','exc_info','excepthook','exec_prefix','executable','exit','flags','float_info','float_repr_style','getcheckinterval','getdefaultencoding','getdlopenflags','getfilesystemencoding','getobjects','getprofile','getrecursionlimit','getrefcount','getsizeof','getswitchinterval','gettotalrefcount','gettrace','hash_info','hexversion','implementation','int_info','intern','maxsize','maxunicode','meta_path','modules','path','path_hooks','path_importer_cache'、'平台'、'前缀'、'ps1','setcheckinterval','setdlopenflags','setprofile','setrecursionlimit','setswitchinterval','settrace','stderr','stdin','stdout','thread_info','version','version_info','warnoptions']如果没有给出参数,dir()函数将列出当前定义的所有名称:a=[1,2,3,4,5]importfibofib=fibo.fibprint(dir())#Get当前模块中定义的属性列表#['__builtins__','__name__','a','fib','fibo','sys']b=5#创建一个新变量'a'print(dir())#['__annotations__','__builtins__','__cached__','__doc__','__file__','__loader__','__name__','__package__','__spec__','a','b']delb#删除变量名aprint(dir())#['__annotations__','__builtins__','__cached__','__doc__','__file__','__loader__','__name__','__package__','__spec__','a']三、模块查找路径1、导入模块时查找模块的顺序1、先查找内存中已经导入的模块。如果我们在运行run.py文件时快速删除mmm.py文件,我们会发现该文件会继续运行而不会报错,因为mmm已经导入内存了。再次运行run.py会报错,因为mmm.py已经被删除了。#test.pyimportm1#从m1.py文件导入,则生成m1模块的命名空间importtime#删除m1.py文件,m1模块的命名空间仍然存在time.sleep(10)importm1#No如果报错,m1模块肯定不是从文件中获取,而是从内存中获取。2.内置模块验证首先在内置中找到,而不是首先在自定义的time.py文件中找到。#time.pyprint('fromtime.py')#run.pyimporttimeprint(time)#3、在环境变量sys.path中找到(强调:sys.path的第一个值是当前的位置执行文件夹)importsysforninsys.path:print(n)#C:\PycharmProjects\untitled\venv\Scripts\python.exeC:/PycharmProjects/untitled/hello.py#C:\PycharmProjects\untitled#C:\PycharmProjects\untitled#C:\Python\Python38\python38.zip#C:\Python\Python38\DLLs#C:\Python\Python38\lib#C:\Python\Python38#C:\PycharmProjects\untitled\venv#C:\PycharmProjects\untitled\venv\lib\site-packages如果mmm.py在C:\PycharmProjects\untitled\day16路径下,执行文件路径为C:\PycharmProjects\untitled,如果是正常导入会报错,我们可以在环境变量sys.path中加入C:\PycharmProjects\untitled\day16来防止出错。#run.pyimportsyssys.path.append(r'C:\PycharmProjects\untitled\day16')print(sys.path)importmmmmmm.f1()2.搜索路径以可执行文件为准。假设我们有如下目录结构中的文件,文件中代码为:hello和spam.py不在同一个目录下,所以run.py的环境变量不能直接找到m2,需要从thefolderfromaaimportspamprint(spam.money)4.Python文件的两种用法当一个模块第一次被另一个程序引入时,它的主程序就会运行。如果我们不想在导入模块时执行模块中的块,我们可以使用__name__属性使该块仅在模块本身运行时执行。一个python文件一共有两个用途,一个是执行文件;另一个是作为模块导入。每个模块都有一个__name__属性。当它的值为'__main__'时,表示模块本身正在运行,否则为导入。1、run.py运行时,aaa.py被认为是引用模块,其__name__=='aaa'(模块名),会执行aaa.py中的f1()。#aaa.pyx=1deff1():print('fromf1')f1()#run.pyimportaaa2,当aaa.py被视为可执行文件时,加上__name__=='__main__',单独运行aaa.py将在aaa.py中执行f1()。防止在run.py运行时执行f1()。#aaa.pyx=1deff1():print('fromf1')if__name__=='__main__':f1()五、包是Python模块命名空间的一种管理形式,包的本质是一个文件夹包含.py文件。包采用“点模块名称”。例如,如果模块的名称是A.B,则它代表包A中的子模块B。只有当目录包含名为__init__.py的文件时,才将其视为包。导入包时,Python会根据sys.path中的目录查找包中包含的子目录。导入包时会发生三件事:创建包命名空间由于包是一个文件夹,无法执行包,所以执行包下的.py文件,执行过程中生成的名称存放在包命名空间中(也就是package命名空间中存放的名字都是来自.py)在当前执行文件中获取一个名字aaa,aaa指的是该包命名空间的importpackage就是import包下的.py,importm1是导入m1__init__。1.两种导入方式:import...:importitem.subitem.subsubitem这种导入形式,除了最后一项,必须是包,最后一项可以是模块也可以是包,但不能是类,函数或变量的名称。from...import...:当使用frompackageimportitem形式时,对应的item可以是包中的子模块(subpackage),也可以是包中定义的其他名称,如函数、类或变量。2.importimportimportmodulesinapackageimport一次只能导入一个包中的特定模块,而且他必须使用全名才能访问。importaaa.bbb.m3print(aaa.bbb.m3.func3())import方法无法导入函数和变量:importaaa.bbb.m3.f3错误3、fromimport方法:导入模块中的特定模块。不需要那些冗长的前缀来访问fromaaa.bbbimportm3print(m3.func3())来导入模块中的特定函数这种方式不需要那些冗长的前缀来访问fromaaa.bbb.m3importfunc3print(func3())4.绝对导入和相对导入绝对导入:#aaa/.pyfromaaa.m1importfunc1fromaaa.m2importfunc2相对导入:.代表当前导入文件所在的文件夹..代表当前导入文件的上层thefolderwhereitislocated...代表当前导入文件所在文件夹的上层。from.m1importfunc1from.m2importfunc25,from...import*import语句遵循以下规则:如果包定义文件init__.py中有一个名为__all的列表变量,那么使用frompackageimport*时,此列表中的所有名称都将作为包内容导入。这是一个示例,其中包含以下代码:file:sounds/effects/__init__.py:__all__=["echo","surround","reverse"]这意味着当您使用fromsound.effectsimport*thisusage,你只会在包中导入这三个子模块。6、软件开发的目录规范为了提高程序的可读性和可维护性,我们应该为软件设计一个良好的目录结构,这与规范的编码风格同样重要。简而言之,就是将软件代码划分到文件目录中。假设你要写一个ATM软件,你可以按照下面的目录结构来管理你的软件代码:ATM/|--core/||--src.py#业务核心逻辑代码||--接口/||--api.py#接口文件||--分贝/||--db_handle.py#操作数据文件||--db.txt#存储数据文件||--库/||--common.py#分享功能||--会议/||--settings.py#配置相关||--箱子/||--run.py#程序的启动文件一般放在项目的根目录下,因为它会默认使用运行文件所在的文件夹作为sys.path的第一个路径,这样就保存了处理环境变量的步骤||--日志/||--log.log#日志文件||--requirements.txt#存放软件依赖的外部Python包列表,见https://pip.readthedocs.io/en/1.1/requirements.html|--README#项目描述文件settings.py#settings.py导入o??sBASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))DB_PATH=os.path.join(BASE_DIR,'db','db.txt')LOG_PATH=os.path.join(BASE_DIR,'log','user.log')#print(DB_PATH)#print(LOG_PATH)common.py#common.py从conf导入设置导入时间deflogger(msg):current_time=time.strftime('%Y-%m-%d%X')以open(settings.LOG_PATH,mode='a',encoding='utf-8')asf:f.write('%s%s'%(current_time,msg))src.py#src.pyfromconfimportsettingsfromlibimportcommondeflogin():print('login')defregister():print('register')name=input('username>>:')pwd=input('password>>:')withopen(settings.DB_PATH,mode='a',encoding='utf-8')asf:f.write('%s:%s\n'%(name,pwd))#记录日志。....common.logger('%s注册成功'%name)print('注册成功')defshopping():print('shopping')defpay():print('payment')deftransfer():print('transfer')func_dic={'1':login,'2':register,'3':shopping,'4':pay,'5':transfer,}defrun():whileTrue:print("""1登录2注册3购物4支付5转账6退出""")choice=input('>>>:').strip()ifchoice=='6':breakifchoicenotinfunc_dic:print('input错误的命令,愚蠢的fork')continuefunc_dic[choice]()run.py#run.pyimportsysimportosBASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))sys.path.append(BASE_DIR)fromcoreimportsrc如果__name__=='__main__':src.run()