自己编写的python代码经常需要分模块文件以及包,梳理一下调用顺序、执行顺序、工作路径、函数与变量等

工作路径

首先是工作路径,当模块代码放在统一的包内的时候,其路径和外层的包路径不同,当作为主调用时,工作路径是该模块所在的路径,而作为模块import进时,工作路径是主调用的路径

这是PyTest/utils/utils.py文件,输出路径,并定义了一个输出路径函数

 import sys

 def printpath():
print('function')
print(sys.path[0])
print('function end') print('utils main')
print(sys.path[0])
print('utils main end')

在该目录下运行它,得到的是:

 zry@seupalm:~/PyTest/utils$ python utils.py
utils main
/home/zry/PyTest/utils
utils main end

毫无疑问,路径就是当前路径。

在外层的文件PyTest/fun.py:

 import sys
from utils.utils import * print('fun main')
print(sys.path[0])
printpath()
print('fun main end')

这里该代码调用了utils/utils.py的内容,运行结果:

 zry@seupalm:~/PyTest$ python fun.py
utils main
/home/zry/PyTest
utils main end
fun main
/home/zry/PyTest
function
/home/zry/PyTest
function end
fun main end

可以发现,所有的路径输出都是主调用的路径了。因此需要注意的其实是,在工具包的模块里,考虑避免设置固定路径,因为作为模块被调用时,并不确定工作路径是什么

执行顺序

此外,还可以发现import时utils.py先于fun.py的内容运行,因此,在import时其实是将utils.py这个模块运行了一遍的,如果仅希望引入函数,而不希望运行代码,则可以在不希望运行的代码前加上if __name__ == '__main__':

即仅在作为主调用时才运行,注意此处name和main两边都是两个下划线

修改PyTest/utils/utils.py:

 import sys

 def printpath():
print('function')
print(sys.path[0])
print('function end') if __name__ == '__main__':
print('utils main')
print(sys.path[0])
print('utils main end')

此时重新运行PyTest/fun.py:

 zry@seupalm:~/PyTest$ python fun.py
fun main
/home/zry/PyTest
function
/home/zry/PyTest
function end
fun main end

就不会运行utils.py的主函数部分了

模块内变量

如果没有加上判断__name__的语句,实际是在import时就会运行一遍,所以对于from utils.utils import *这种操作同样会将模块里的变量也引入进来

仍然修改PyTest/utils/utils.py:

 import sys

 def printpath():
print('function')
print(sys.path[0])
print('function end') a = 'hello world'
print('utils main')
print(sys.path[0])
print('utils main end')

并在fun.py中输出a得到:

 zry@seupalm:~/PyTest$ python fun.py
utils main
/home/zry/PyTest
utils main end
fun main
/home/zry/PyTest
function
/home/zry/PyTest
function end
hello world
fun main end

可以看到hello world被输出了。

引入指定函数方法

但如果是仅引入一个函数方法呢,即使用from utils/utils import printpath:

修改PyTest/fun.py:

 import sys
from utils.utils import printpath print('fun main')
print(sys.path[0])
printpath()
print(a)
print('fun main end')

运行:

 zry@seupalm:~/PyTest$ python fun.py
utils main
/home/zry/PyTest
utils main end
fun main
/home/zry/PyTest
function
/home/zry/PyTest
function end
Traceback (most recent call last):
File "fun.py", line , in <module>
print(a)
NameError: name 'a' is not defined

可以看到PyTest/utils/utils.py仍然被运行了一遍,但是过程中的变量则并不会被引入,因为只引入了指定的函数方法。

跨级调用

当需要跨级import时,如果是主调用直接import进来,则并不需要担心

编写PyTest/utils/src/uu.py

 import sys

 def uufun():
print('uufun')
print(sys.path[0])
print('uufun end')

PyTest/fun.py

 import sys
from utils.src.uu import * print('fun main')
uufun()
print('fun main end')

运行fun.py

 zry@seupalm:~/PyTest$ python fun.py
fun main
uufun
/home/zry/PyTest
uufun end
fun main end

可以看出是成功调用了的

但如果希望用PyTest/utils/utils.py调用PyTest/utils/src/uu.py,再用PyTest/fun.py调用PyTest/utils/utils.py,则会出现问题

修改PyTest/utils/utils.py,增加一行:

 from src.uu import uufun

此时运行PyTest/utils/utils.py仍然没有问题

但修改PyTest/fun.py来调用PyTest/utils/utils.py,import改为:

 from utils.utils import *

 from utils.utils import printpath

运行结果都会出现报错

 zry@seupalm:~/PyTest$ python fun.py
Traceback (most recent call last):
File "fun.py", line , in <module>
from utils.utils import printpath
File "/home/zry/PyTest/utils/utils.py", line , in <module>
from src.uu import uufun
ModuleNotFoundError: No module named 'src'

此时很显然就是import语句的路径也是根据主调用得来的,所以在二级调用时路径也会出现问题

如果用比较暴力的解决办法,就将PyTest/utils/utils.py里import的路径变为utils.src.uu,这样就能够二级调用了,而如果是import *的形式,则会将PyTest/utils/utils.py里import得到的PyTest/utils/src/uu.py内函数一并引入主调用。

但如果遇到不希望改动内层的代码,毕竟对于内层来说,文件目录层级并不是这样的,那么可以怎么办呢?

由于开发经历仍然有限,我采取的是如下方法:

此时PyTest是主目录,PyTest/utils是一级目录,PyTest/utils/src是二级目录,首先在一级目录下放置一个__init__.py空文件,这是为了让主目录下的代码import一级目录的内容时,可以将整个一级目录视为一个包,当然import一级目录的内容时首先会运行__init__.py,此处因为是空文件,所以只是让一级目录能够作为包被识别。

然后在主目录下的函数调用一级目录下的内容时,将一级目录的路径加入系统路径,这样就不用修改一级目录内部的东西了。

具体是将PyTest/fun.py进行如下修改:

 import sys
sys.path.append('utils')
from utils.utils import * print('fun main')
uufun()
print('fun main end')

此时就能够正常运行,并通过一级目录的模块调用到二级目录的内容了。当然,添加路径的语句也可以放在一级目录的__init__.py里,毕竟运行顺序是一样的。

不过如果后续开发又把主目录当成模块,进行了三级调用呢……这样utils这个路径也是相对路径,是不是仍然需要修改此时的一级目录内容呢……emmmm没有测试过,我觉得还是好好设计好项目结构比较好23333

Python 模块调用的变量与路径的更多相关文章

  1. Python模块调用方式详解

    Python模块调用方式详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其 ...

  2. python 模块调用的几种方式

    在python里面又很多模块,或者引用第三方模块,python 模块调用的几种方式,下面详细解说 1,import 模块名 2,from 模块 import  模块里面的小功能 3,from  模块 ...

  3. Python开发【第一篇】Python模块中特殊变量

    模块中特殊变量 生产环境中,常用的就是__name__和__file__ __doc__ __package__ __cached__ __name__ __file__ 一. __doc__  #获 ...

  4. python - 模块调用

    基础 调用模块常见的两种方法 import [模块名] from [模块名] import [属性/方法] 进阶用法 调用父级目录下模块 背景介绍 目录new2(b2.py)调用上级目录new1(b1 ...

  5. python模块调用

    1.某个模块1被调用到另一个模块2的时候,当不想模块1中的某些代码在模块2中执行时,可以在模块一种添加如下代码: if    __name__  ==     "__main__" ...

  6. Python模块学习:glob 文件路径查找

    glob模块是最简单的模块之一,内容非常少. 用它可以查找符合特定规则的文件路径名.跟使用windows下的文件搜索差不多. 查找文件只用到三个匹配符:”*”, “?”, “[]”. ”*”匹配0个或 ...

  7. python 模块之间的变量共享

    才疏学浅,只知道两种方式: 1. 通过__builtin__实现: builtin1.py import __builtin__ __builtin__.some_global_var_among_m ...

  8. Python模块、包、异常、文件(案例)

    Python模块.包.异常.文件(案例) python.py #模块 # Python中的模块(Module),是一个Python文件,以.py文件结尾,包含了Python对象定义和Python语句, ...

  9. 4.1 python中调用rust程序

    概述 使用rust-cpython将rust程序做为python模块调用: 通常为了提高python的性能: 参考 https://github.com/dgrunwald/rust-cpython ...

随机推荐

  1. h264文件分析(纯c解析代码)

    参考链接:1. 解析H264的SPS信息 https://blog.csdn.net/lizhijian21/article/details/80982403               2. h.2 ...

  2. Linux下数据库备份

    1.登录数据库服务器并切换到数据库用户下 [root@*** ~]# su - oracle 2.测试用户名密码是否能正确连接数据库 [oracle@*** ~]$ sqlplus username/ ...

  3. 微信机器人 返现机器人 pc版本 移动版本 java开发 小范省钱

    微信机器人 返现机器人 pc版本 移动版本 java开发 小范省钱 微信搜索微信号 fanli-x 或 扫描下方二维码,可查看效果. 非web版微信,pc/移动版微信 支持新号24小时 不封号! 有任 ...

  4. CSS多行文字超出隐藏加省略号

    overflow: hidden; text-overflow:ellipsis; white-space: nowrap; 限制行数 overflow: hidden; text-overflow: ...

  5. 局域网主机A向主机B发送ip数据报的过程

    主机A首先查找其ARP高速缓存内的映射表中是否有主机B的IP地址,如果有,则查找出其对应的硬件地址,并将该硬件地址写入MAC帧,通过局域网将该MAC帧发送给主机B.如果ARP高速缓存内没有主机B的IP ...

  6. org.hibernate.AssertionFailure: null id in xxx entry (don't flush the Session after an exception occurs)

    网上找了很久,发现造成原因有很多种,后来终于发现了端倪:看提示是发生了异常,查看业务代码,发现有这个逻辑:先插入记录,如果有唯一键约束异常(并发造成),catch时查询已存在的记录,查询的时候就报了此 ...

  7. 三,用户交互方式与python基本数据类型

    一.与用户交互 input python2中:用户输入什么类型的数据,就储存为什么类型的数据.比如输入数字则储存为整型,输入符号则存储为字符串型.raw_input会将所有输入的类型转换为字符串型. ...

  8. Linux 驱动——Button驱动4(fasync)异步通知

    button_drv.c驱动文件: #include <linux/module.h>#include <linux/kernel.h>#include <linux/f ...

  9. [转] CMake

    转载地址:https://www.cnblogs.com/lidabo/p/7359422.html cmake 简介 CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装( ...

  10. java2周来的一些心得和体会

    1.首先,在开发的一开始,可以将绝大多数rest可能提交过来字段先抽离出来,做成一个基础类. 然后再继承这个类,这样做的好处是业务就被分开了,谁也不会影响到谁. 2.在maven当中,需要修改自己的类 ...