标签:pycharm ade style bit 决定 应该 pyc 理解 其他
1 #my_module.py 2 print(‘from the my_module.py‘) 3 4 money=1000 5 6 def read1(): 7 print(‘my_module->read1->money‘,money) 8 9 def read2(): 10 print(‘my_module->read2 calling read1‘) 11 read1() 12 13 def change(): 14 global money 15 money=0 16 17 my_module模块
1.1.1
1 #demo.py 2 import my_module #只在第一次导入时才执行my_module.py内代码,此处的显式效果是只打印一次‘from the my_module.py‘,当然其他的顶级代码也都被执行了,只不过没有显示效果. 3 import my_module 4 import my_module 5 import my_module 6 7 ‘‘‘ 8 执行结果: 9 from the my_module.py 10 ‘‘‘ 11 12 demo.py
我们可以从sys.modules(字典)中找到当前已经加载的模块,sys.modules是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
1 #测试一:money与my_module.money不冲突 2 #demo.py 3 import my_module 4 money=10 5 print(my_module.money) 6 7 ‘‘‘ 8 执行结果: 9 from the my_module.py 10 ‘‘‘ 11 12 测试一:money与my_module.money不冲突
1 #测试二:read1与my_module.read1不冲突 2 #demo.py 3 import my_module 4 def read1(): 5 print(‘========‘) 6 my_module.read1() 7 8 ‘‘‘ 9 执行结果: 10 from the my_module.py 11 my_module->read1->money 1000 12 ‘‘‘ 13 14 测试二:read1与my_module.read1不冲突
1 #测试三:执行my_module.change()操作的全局变量money仍然是my_module中的 2 #demo.py 3 import my_module 4 money=1 5 my_module.change() 6 print(money) 7 8 ‘‘‘ 9 执行结果: 10 from the my_module.py 11 ‘‘‘ 12 13 测试三:执行my_module.change()操作的全局变量money仍然是my_module中的
1.1.3
1 1 提示:导入模块时到底执行了什么? 2 2 3 3 In fact function definitions are also ‘statements’ that are ‘executed’; the execution of a module-level function definition enters the function name in the module’s global symbol table. 4 4 事实上函数定义也是“被执行”的语句,模块级别函数定义的执行将函数名放入模块全局名称空间表,用globals()可以查看
3.创建名字my_module来引用该命名空间
1 1 这个名字和变量名没什么区别,都是‘第一类的’,且使用my_module.名字的方式可以访问my_module.py文件中定义的名字,my_module.名字与test.py中的名字来自两个完全不同的地方。
4.为模块起别名,相当于m1=1,m2=m1
1 import my_module as sm
2 print(sm.money)
示范用法一:
有两中sql模块mysql和oracle,根据用户的输入,选择不同的sql功能
1 #mysql.py 2 def sqlparse(): 3 print(‘from mysql sqlparse‘) 4 #oracle.py 5 def sqlparse(): 6 print(‘from oracle sqlparse‘) 7 8 #test.py 9 db_type=input(‘>>: ‘) 10 if db_type == ‘mysql‘: 11 import mysql as db 12 elif db_type == ‘oracle‘: 13 import oracle as db 14 15 db.sqlparse() 16 复制代码 17 18 示例用法1
示范用法二:
1 if file_format == ‘xml‘: 2 import xmlreader as reader 3 elif file_format == ‘csv‘: 4 import csvreader as reader 5 data=reader.read_date(filename)
5.在一行导入多个模块
1 import sys,os,re
from my_module import read1,read2
1 #测试一:导入的函数read1,执行时仍然回到my_module.py中寻找全局变量money 2 #demo.py 3 from my_module import read1 4 money=1000 5 read1() 6 ‘‘‘ 7 执行结果: 8 from the my_module.py 9 spam->read1->money 1000 10 ‘‘‘ 11 12 #测试二:导入的函数read2,执行时需要调用read1(),仍然回到my_module.py中找read1() 13 #demo.py 14 from my_module import read2 15 def read1(): 16 print(‘==========‘) 17 read2() 18 19 ‘‘‘ 20 执行结果: 21 from the my_module.py 22 my_module->read2 calling read1 23 my_module->read1->money 1000 24 ‘‘‘
如果当前有重名read1或者read2,那么会有覆盖效果。
1 #测试三:导入的函数read1,被当前位置定义的read1覆盖掉了 2 #demo.py 3 from my_module import read1 4 def read1(): 5 print(‘==========‘) 6 read1() 7 ‘‘‘ 8 执行结果: 9 from the my_module.py 10 ========== 11 ‘‘‘
需要特别强调的一点是:python中的变量赋值不是一种存储操作,而只是一种绑定关系,如下:
1 from my_module import money,read1 2 money=100 #将当前位置的名字money绑定到了100 3 print(money) #打印当前的名字 4 read1() #读取my_module.py中的名字money,仍然为1000 5 6 ‘‘‘ 7 from the my_module.py 8 my_module->read1->money 1000 9 ‘‘‘
1.2.2
from my_module import read1 as read
1 from my_module import (read1, 2 read2, 3 money)
1.2.4
1 from my_module import * #将模块my_module中所有的名字都导入到当前名称空间 2 print(money) 3 print(read1) 4 print(read2) 5 print(change) 6 7 ‘‘‘ 8 执行结果: 9 from the my_module.py 10 <function read1 at 0x1012e8158> 11 <function read2 at 0x1012e81e0> 12 <function change at 0x1012e8268> 13 ‘‘‘
在my_module.py中新增一行
1 __all__=[‘money‘,‘read1‘] #这样在另外一个文件中用from my_module import *就这能导入列表中规定的两个名字
*如果my_module.py中的名字前加_,即_money,则from my_module import *,则_money不能被导入
1 考虑到性能的原因,每个模块只被导入一次,放入字典sys.modules中,如果你改变了模块的内容,你必须重启程序,python不支持重新加载或卸载之前导入的模块, 2 3 有的同学可能会想到直接从sys.modules中删除一个模块不就可以卸载了吗,注意了,你删了sys.modules中的模块对象仍然可能被其他程序的组件所引用,因而不会被清除。 4 5 特别的对于我们引用了这个模块中的一个类,用这个类产生了很多对象,因而这些对象都有关于这个模块的引用。 6 7 如果只是你想交互测试的一个模块,使用 importlib.reload(), e.g. import importlib; importlib.reload(modulename),这只能用于测试环境。
1.3把模块当做脚本执行
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于‘__main__‘
当做模块导入:
__name__= 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == ‘__main__‘:
1 def fib(n): 2 a, b = 0, 1 3 while b < n: 4 print(b, end=‘ ‘) 5 a, b = b, a+b 6 print() 7 8 if __name__ == "__main__": 9 print(__name__) 10 num = input(‘num :‘) 11 fib(int(num))
1.4 模块搜索路径
python解释器在启动时会自动加载一些模块,可以使用sys.modules查看
在第一次导入某个模块时(比如my_module),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
如果没有,解释器则会查找同名的内建模块,如果还没有找到就从sys.path给出的目录列表中依次寻找my_module.py文件。
所以总结模块的查找顺序是:内存中已经加载的模块->内置模块->sys.path路径中包含的模块
sys.path的初始化的值来自于:
The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
The installation-dependent default.
需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。
在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。
1 1 >>> import sys 2 2 >>> sys.path.append(‘/a/b/c/d‘) 3 3 >>> sys.path.insert(0,‘/x/y/z‘) #排在前的目录,优先被搜索
注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理。
1 #官网链接:https://docs.python.org/3/tutorial/modules.html#the-module-search-path 2 搜索路径: 3 当一个命名为my_module的模块被导入时 4 解释器首先会从内建模块中寻找该名字 5 找不到,则去sys.path中找该名字 6 7 sys.path从以下位置初始化 8 执行文件所在的当前目录 9 PTYHONPATH(包含一系列目录名,与shell变量PATH语法一样) 10 依赖安装时默认指定的 11 12 注意:在支持软连接的文件系统中,执行脚本所在的目录是在软连接之后被计算的,换句话说,包含软连接的目录不会被添加到模块的搜索路径中 13 14 在初始化后,我们也可以在python程序中修改sys.path,执行文件所在的路径默认是sys.path的第一个目录,在所有标准库路径的前面。这意味着,当前目录是优先于标准库目录的,需要强调的是:我们自定义的模块名不要跟python标准库的模块名重复,除非你是故意的,傻叉。
1.5 编译python文件
import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
1 import os 2 os.makedirs(‘glance/api‘) 3 os.makedirs(‘glance/cmd‘) 4 os.makedirs(‘glance/db‘) 5 l = [] 6 l.append(open(‘glance/__init__.py‘,‘w‘)) 7 l.append(open(‘glance/api/__init__.py‘,‘w‘)) 8 l.append(open(‘glance/api/policy.py‘,‘w‘)) 9 l.append(open(‘glance/api/versions.py‘,‘w‘)) 10 l.append(open(‘glance/cmd/__init__.py‘,‘w‘)) 11 l.append(open(‘glance/cmd/manage.py‘,‘w‘)) 12 l.append(open(‘glance/db/models.py‘,‘w‘)) 13 map(lambda f:f.close() ,l) 14 15 创建目录代码
2.1注意事项
我们在与包glance同级别的文件中测试
1 1 import glance.db.models 2 2 glance.db.models.register_models(‘mysql‘)
1 1 from glance.db import models 2 2 models.register_models(‘mysql‘) 3 3 4 4 from glance.db.models import register_models 5 5 register_models(‘mysql‘)
1 #在__init__.py中定义 2 x=10 3 4 def func(): 5 print(‘from api.__init.py‘) 6 7 __all__=[‘x‘,‘func‘,‘policy‘]
此时我们在于glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。
绝对导入:以glance作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
1 在glance/api/version.py 2 3 #绝对导入 4 from glance.cmd import manage 5 manage.main() 6 7 #相对导入 8 from ..cmd import manage 9 manage.main()
测试结果:注意一定要在于glance同级的文件中测试
from glance.api import versions
import policy policy.get()
没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到
但是你想啊,你子包中的模块version.py极有可能是被一个glance包同一级别的其他文件导入,比如我们在于glance同级下的一个test.py文件中导入version.py,如下
1 from glance.api import versions 2 3 ‘‘‘ 4 执行结果: 5 ImportError: No module named ‘policy‘ 6 ‘‘‘ 7 8 ‘‘‘ 9 分析: 10 此时我们导入versions在versions.py中执行 11 import policy需要找从sys.path也就是从当前目录找policy.py, 12 这必然是找不到的 13 ‘‘‘
1 glance/ 2 3 ├── __init__.py from glance import api 4 from glance import cmd 5 from glance import db 6 7 ├── api 8 9 │ ├── __init__.py from glance.api import policy 10 from glance.api import versions 11 12 │ ├── policy.py 13 14 │ └── versions.py 15 16 ├── cmd from glance.cmd import manage 17 18 │ ├── __init__.py 19 20 │ └── manage.py 21 22 └── db from glance.db import models 23 24 ├── __init__.py 25 26 └── models.py 27 28 绝对导入
1 glance/ 2 3 ├── __init__.py from . import api #.表示当前目录 4 from . import cmd 5 from . import db 6 7 ├── api 8 9 │ ├── __init__.py from . import policy 10 from . import versions 11 12 │ ├── policy.py 13 14 │ └── versions.py 15 16 ├── cmd from . import manage 17 18 │ ├── __init__.py 19 20 │ └── manage.py from ..api import policy 21 #..表示上一级目录,想再manage中使用policy中的方法就需要回到上一级glance目录往下找api包,从api导入policy 22 23 └── db from . import models 24 25 ├── __init__.py 26 27 └── models.py 28 29 相对导入
#在与glance同级的test.py中 import glance glance.cmd.manage.main() ‘‘‘ 执行结果: AttributeError: module ‘glance‘ has no attribute ‘cmd‘ ‘‘‘
解决方法:
1 #glance/__init__.py 2 from . import cmd 3 4 #glance/cmd/__init__.py 5 from . import manage
1 1 #在于glance同级的test.py中 2 2 import glance 3 3 glance.cmd.manage.main()
千万别问:__all__不能解决吗,__all__是用于控制from...import *
1 glance/ 2 3 ├── __init__.py from .api import * 4 from .cmd import * 5 from .db import * 6 ├── api 7 8 │ ├── __init__.py __all__ = [‘policy‘,‘versions‘] 9 10 │ ├── policy.py 11 12 │ └── versions.py 13 14 ├── cmd __all__ = [‘manage‘] 15 16 │ ├── __init__.py 17 18 │ └── manage.py 19 20 └── db __all__ = [‘models‘] 21 22 ├── __init__.py 23 24 └── models.py 25 26 27 import glance 28 policy.get() 29 30 import glance
标签:pycharm ade style bit 决定 应该 pyc 理解 其他
原文地址:https://www.cnblogs.com/wr13640959765/p/9323042.html