1.目录 directory 与包package的区别
模块的定义:本质就是以 .py 结尾的python文件,模块的目的是为了其他程序进行引用。
目录(Dictionary):
Dictionary在pycharm中就是一个文件夹,放置资源文件,对应于在进行JavaWeb开发时用于放置css/js文件的目录,或者说在进行物体识别时,用来存储背景图像的文件夹。该文件夹其中并不包含__init.py__文件
包(Package):
对于Python package 文件夹而言,与Dictionary不同之处在于其会自动创建__init__.py文件。 简单的说,python package就是一个目录,其中包括一组模块和一个__init__.py文件。
2.导入模块
导入模块的方法:
import module_name
import module1_name, module2_name
from module_name import * #---> 一般import * 不建议使用
from module_name import m1,m2,m3 #---> m1为module_name下面的方法或变量
from module_name import logger as logger_a #---> 为导入的变量或方法取个别名,引用时直接用别名
2.1 同级目录下模块的导入

在 main_day41.py中导入para_day41.py,两种方法:
# 方法一:
# 相当于把 para_day41.py 中的所有代码拷贝过来赋值给变量 para_day41 ,引用时直接用 "该变量."
import para_day41
# 变量.xxx 调用
para_day41.show_para()
# 运行结果:
the para_day41
#方法二: 只把 para_day41.py 中 name 变量和 show_para 方法拷贝过来,可以直接用(推荐用该方法)
from para_day41 import name,show_para
print(name)
show_para()
运行结果:
D:\python365\python3.exe D:/Pyexample/20190220Day4/main_day41.py
para_day41
in the para_day41
2.2不同级目录下模块的导入:
(1)导入子目录下的模块
main.py 中导入 day51 目录下面 para_day51.py:
import day51.para_day51
day51.para_day51.show_para()
from day51.para_day51 import *
show_para()
from day51 import para_day51
para_day51.show_para()
运行结果:
D:\python365\python3.exe D:/Pyexample/20190220Day5/main.py
in the para_day51
(2)导入上级目录下的模块 --- 重要
day22 目录下面的 main_day22.py 导入 day21 目录下的 para_day21.py
注:执行 main_day22.py 时,要导入 day21 目录下的 para_day21.py,具体的搜索路径是这样的:
首先,python需要在当前目录下去找 para_day21.py,发现没有,然后就到 sys.path 列表中的每个路径下面去找:
['D:\\Pyexample\\20190220Day2\\day22', 'D:\\Pyexample', 'D:\\Pyexample\\W3', 'D:\\Pyexample\\20181113', 'D:\\Pyexample\\CSP\\cspmonitor', 'D:\\Pyexample\\python', 'D:\\python365\\python36.zip', 'D:\\python365\\DLLs', 'D:\\python365\\lib', 'D:\\python365', 'D:\\python365\\lib\\site-packages']
如果不在该列表中,则无法导入
(3)手动添加sys.path
import sys,os
p = os.path.dirname( # 上一级目录路径
os.path.dirname( # 本级目录路径
os.path.abspath(__file__) # 本级文件路径
)
)
sys.path.append(BASE_DIR)
这样就把上一级目录添加进来了,可以导入了。
(4)打印当前目录
os.getcwd()
# >>>''D:\\workspace\\爬虫文档整理\\08-软件谷oceanspider\\oceanspider'
os.path.abspath(os.curdir)
# >>>''D:\\workspace\\爬虫文档整理\\08-软件谷oceanspider\\oceanspider'
os.path.abspath('.')
# >>>''D:\\workspace\\爬虫文档整理\\08-软件谷oceanspider\\oceanspider'
sys.path[0]
# >>>''D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pydev'
sys.argv[0]
# >>>''D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pydev\\pydevconsole.py'
sys.argv
# >>>'['D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pydev\\pydevconsole.py', '--mode=client', '--port=55166']
sys.path
# >>>['D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pydev', 'D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pycharm_display', 'D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\third_party\\thriftpy', 'D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pydev', 'C:\\Users\\Administrator\\Envs\\ocean\\Scripts\\python36.zip', 'd:\\softwareplace\\python3.6.6\\DLLs', 'd:\\softwareplace\\python3.6.6\\lib', 'd:\\softwareplace\\python3.6.6', 'C:\\Users\\Administrator\\Envs\\ocean', 'C:\\Users\\Administrator\\Envs\\ocean\\lib\\site-packages', 'D:\\SoftwarePlace\\JetBrains\\PyCharm 2021.2.1\\plugins\\python\\helpers\\pycharm_matplotlib_backend', 'D:\\workspace\\爬虫文档整理\\08-软件谷oceanspider\\oceanspider', 'D:\\workspace\\爬虫文档整理\\08-软件谷oceanspider\\oceanspider\\restback', 'D:/workspace/爬虫文档整理/08-软件谷oceanspider/oceanspider']
os.getcwd()、os.path.abspath(os.curdir)、os.path.abspath('.')在以上三种情况下的结果都是执行文件所在的目录
sys.argv[0]是当前执行的Python脚本的文件名,不一定是当前的路径。
sys.path[0]是当前系统环境变量的第一个值。当运行.py和以生成多文件模式打包的可执行文件时,输出结果是程序的当前目录。而由单文件模式打包生成的可执行文件,输出结果是系统的默认当前工作目录。
由于os.getcwd()、os.path.abspath(os.curdir)、os.path.abspath('.')是获取的当前python 的工作目录,而工作目录是可以通过os.chdir(path)更改的。
os.chdir(path):改变当前工作目录到指定路径path。
所以如果想要获取当前路径,最稳定的方法是:os.path.dirname(sys.argv[0])
三、导入包
导入包的本质就是执行这个包下面的init.py文件
1.同级路径下包的导入:

main.py中导入包day31,直接用import 包名即可
import day31
(1)__init__.py中没有内容时
D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py Process finished with exit code 0
(2)__init__.py中有内容时:

D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py
in the day31 __init__
Process finished with exit code 0
2.不同级路径下包的导入:

前提:需要将要导入的包所在的路径添加到 sys.path 列表中,方法同上,不再赘述。
3. 导入包中的模块
只是导入一个包并没有什么实际意义,包是用来从逻辑上组织模块的,所以实际项目中更多的是导入包中的模块,导入包中模块的方法:
from Package1 import Module1
from Package1 import Package2
from Package1.Module1 import m1,m2 # m1,m2为模块中的变量或方法
from Package1.Module1 import *
import Package1.Module1
import Package1.Package2
要导入的包及其模块结构如下:

(1)在main.py中导入包day31下面的para_day31.py或者para_day32.py模块
import day31.para_day31,day31.para_day32
day31.para_day31.show_para()
day31.para_day32.show_para()
==========================================================
>>>运行结果:
D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py
in the day31 __init__
in the para_day31
in the para_day32
Process finished with exit code 0
或者:
from day31 import para_day31,para_day32
para_day31.show_para()
para_day32.show_para()
============================================================
>>>运行结果:
D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py
in the day31 __init__
in the para_day31
in the para_day32
Process finished with exit code 0
或者:
from day31.para_day31 import show_para,name
print(name) show_para()
============================================================
>>>运行结果:
D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py
in the day31 __init__ para_day31
in the para_day31
Process finished with exit code 0
或者:
from day31.para_day31 import *
print(name)
show_para()
(2)在main.py中导入包day31下面所有的模块,即全部导入
from day31 import *
para_day31.show_para()
para_day32.show_para()
============================================================
>>>运行结果: D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py
in the day31 __init__
Traceback (most recent call last):
File "D:/Pyexample/20190220Day3/main.py", line 35, in <module>
para_day31.show_para()
NameError: name 'para_day31' is not defined
Process finished with exit code 1
此时,需要用到__init__.py文件中的__all__变量,在day31包中的__init__.py文件中定义如下:
"""
@Author:janson
@Date:2019/2/20
@File:__init__
"""
print("in the day31 __init__")
__all__ = ['para_day31','para_day32']
这时 from day31 import * 就会把注册在包__init__.py 文件中__all__列表中的子模块和子包导入到当前作用域中来:
再次运行就不会报错了:
from day31 import *
para_day31.show_para()
para_day32.show_para()
============================================================
>>>运行结果: D:\python365\python3.exe D:/Pyexample/20190220Day3/main.py
in the day31 __init__ in the para_day31
in the para_day32
Process finished with exit code 0
四. pycharm 工程目录结构写代码路径问题
pycharm 默认情况下只检索 项目根目录下的py文件,当引用的py文件不在项目根目录时,会出现错误,类似下边的情况:

解决方法:
只需将要引用的py文件所在的文件夹添加到默认搜索搜索文件夹即可,具体有如下两种方法:
方法一 (推荐)
右键 py 文件所在的文件夹,依次点击:MarkDircetory as -> Sources Root即可。

方法二
将py文件所在文件夹作为一个package,在py文件所在文件夹下新建_init_.py文件,在_init_.py中添加如下语句:
from [py文件所在文件夹名].[py文件名] import 模块名

五. Python_PyCharm中引用同一目录下的模块
如下图,要在main.py中导入networks和manager两个模块;

错误示例:
import networks as net
from manager import Manager, Optimizers
原因: PyCharm工程当前目录在上一层,所以需要从目录开始引用
import src.networks as net
# PyCharm工程当前目录在上一层,所以需要从目录开始引用 from src.manager import Manager, Optimizers
总结


简单的测试

pycharm 中运行:



保证可以 直接在当前目录下运行的时候, 也可以搜索到 其它的包, 不会报错

实际部署的时候设置一个主路口文件, 可以参考django的目录设计


可以看到 在根目录中 导入需要运行的程序, 可以不用 添加父目录以及祖目录,
其实这种好的习惯, 也可以帮我们合理的规划项目
pycharm 这种 自动添加根目录的方式, 给很多小白带来了困惑