python路径sys.path,导入,包,模块

包与模块和普通文件夹

模块

1个py文件是一个模块,一个包,一个文件夹也可以叫做模块,验证:

import torch
import numpy as np
import test_package
from test_package.test_son  import son_py
import test_package.test_son
son_py.hello()
print(test_package.test_son)
print(test_package)
<module 'test_package.test_son' (namespace)>
<module 'test_package' from '/mnt/d/jlu/SphereFormer/test_package/__init__.py'>

直接子目录里面有__init__.py的文件夹(孙目录不行)

包中的init.py

init.py

永远和包一对一绑定,调用包时执行的文件

比如导入A包下的a1.py

from A import a1

执行A的__init__.py再执行a1.py

文件夹:就是不含__init__.py

包和文件夹的区别:

就只有__init__.py的区别,其他我觉得完全没有区别,如上代码,都是模块,都可以作为模块导入。

import

导入加载顺序

from package_A import module_B/package_B中,先执行的是package_A中的__init__.py文件,再执行后面的module_B文件或者package_B中的__init__.py文件。

主要作用

将模块或函数导入到我选定的文件之中。

导入了什么包,import就会执行啥

最简单的情况:A导入了B,如果B是模块,那么会在A执行到import B的地方去执行B模块中的所有代码(已验证)(但是其他执行过的语句、变量、函数除了他import规定的,其他的是看不到的)(不设置全局的代码一般不会耗费太多时间,不管你是只导入了B中的一个变量还是一个函数,都会执行完所有代码),需要注意执行时模块/包 内代码变量都是独立的,也就是并不是简单的我把B的代码接在A之前,之前有过这种理解,是不准确的。

验证红字:

主文件

import torch
import numpy as np
from test_package.hello  import hello

hello.py

def hello():
    print('hello')

print('hello py 其他部分被執行了')
hello py 其他部分被執行了

一个模块导入了其他的某个模块、函数,那么被导入的模块、函数就归该模块所有

结构

son_py.py

from ..hello import hello_func
from .. import hello
def test():
    hello()

hello.py

def hello_func():
    print('hello')

test_tensor.py--主函数

import torch
import numpy as np
import test_package.test_son.son_py as son_py
son_py.hello.hello_func()
son_py.hello_func()

可以看到son_py中并没有hello和hello_func,但因为其引入import了,可以认为son_py获得了hello和hello_func,归该块所有,所以可以使用。但hello.py中如果定义全局的变量a=1,主函数使用son_py.a是调用不到的,使用son_py.hello.a可以调用到。

导入的三种方式

import ,import as

可以导入包和模块,并且重命名

from 。。。import

万能,导入模块,包 ,导入 函数,变量,类(注意不是方法也不是成员变量,意思是不是类里面的东西)

判断用哪个可以根据要导入的类型来使用不同的代码

__name__ 与__main__

import testMoudel
print(__name__)

编辑

__name__就是模块名,主模块的__name__是__main__要注意主模块就是python XXX最开始执行的模块,其他的模块__name__是文件名,比如我A是主模块,A里调用了B,B里又import了A,那么第二次调用的A亲测他不是主模块。

去哪找包-sys.path

sys.path

简介

sys.path在每次调用python命令执行代码时自动生成,且只会生成一次

比如python xxx.py

sys.path提供了包的搜索路径,sys.path一般包括

  • 运行脚本所在的目录,也就是运行py文件的父目录(如果以模块运行则是当前目录)

  • PYTHONPATH 环境变量(类似于 PATH 变量,也是一组目录名组成)

可以由

echo $PYTHONPATH

通常执行结果为空

我们如果要指定动态指定PYTHONPATH,可以添加环境变量

export PYTHONPATH=./

可以做到在每次执行是都将调用python的当前路径加入到sys.path中,当我们(比如在项目文件夹)调用非当前文件夹下的tool/train.py,可以将项目根路径加进去path,就可以调用根路径的模块,非常好用。

  • Python 安装时的默认设置

生成的path在site.py可以看到

我们可以调用

python -m site

来实现查看sys.path,这个path去掉第一个当前路径就是我们的sys.path通常是如何生成的。

sys.path = [
    '/home/RAID0/zxy/code/point-transformer',
    '/home/RAID0/zxy/.conda/envs/pointTrans/lib/python37.zip',
    '/home/RAID0/zxy/.conda/envs/pointTrans/lib/python3.7',
    '/home/RAID0/zxy/.conda/envs/pointTrans/lib/python3.7/lib-dynload',
    '/home/RAID0/zxy/.conda/envs/pointTrans/lib/python3.7/site-packages',
    '/home/RAID0/zxy/.conda/envs/pointTrans/lib/python3.7/site-packages/pointops-0.0.0-py3.7-linux-x86_64.egg',
]

如图第一个是运行脚本所在的目录的path,后五个是安装位置,因为PYTHONPATH在此时我没有设置,为空,所以没有PYTHONPATH添加进来的path

sys.path也反映了找包优先级的问题,最上面的优先级最高

sys.path应该是在运行程序时会定下来(会调用site.py一次),这次运行程序结束之前都不会再改变了,并不是说我sys.path会随着当前所在执行文件的所在目录而随意跳动,因此可以看到别人写的包的模块中调用自己包内的包和模块会使用相对引用来实现。

如何使用pycharm运行模块?(python -m)

编辑

这里有个很小的下三角,点开后再配置就好了,记得修改工作目录为你想运行的位置

注意系统路径和执行路径:

sys.path.append('../../BADet-master')

像这种代码在不同地方执行得到的path是不一样的,比如我有一个文件 a/b/c/test.py里面有上面的这个语句,我在c文件夹内执行

python test.py

那么得到的是a/b/c->a路径,加入的path是a/BADet-master

如果我再a文件夹执行

python a/b/c/test.py

那加入的路径将是 ../../a/b/c的这个路径的BADet-master,都是取决于最终在哪个路径执行的

结论:python中有系统路径(sys.path)和执行路径之说,系统路径是执行时就创建好的也就是sys.path,执行路径是你在运行此代码时终端的位置(pythn a.py此时你终端所处的pwd就是执行路径),除了import找包,其他的搜索比如寻找某一个bin文件,搜寻数据集都是从执行路径来寻找的,系统路径可以包括当前执行路径,就是在使用-m的参数下,或者在py文件的父目录执行代码,也可以做到系统路径和执行路径统一的目的。在py文件内查找路径时都是以执行路径进行查找的。

例如:

执行路径为/home/RAID0/zxy/code/SIENet/tools

该py文件所在路径 /home/RAID0/zxy/code/SIENet/pcdet/datasets/augmentor/database_sampler.py

self.root_path='../data/kitti'

我执行

self.root_path.resolve()

得到的绝对路径步骤 :当然都是在执行路径的基础上得绝对路径

先去掉../得到 /home/RAID0/zxy/code/SIENet 还剩data/kitti

再将data/kitti进行拼接,得/home/RAID0/zxy/code/SIENet/data/kitti

path.resolve:方法会把一个路径或路径片段的序列解析为一个绝对路径。相当于先cd命令,再与执行路径进行拼接得绝对路径,直接调用resolve()则直接跳到与执行路径进行拼接得绝对路径。

相对导入

from . import grok
from .dataset import DatasetTemplate

1表示当前目录

2表示当前目录dataset下的Data。。。。

相对导入格式中:每多一个点,表示更上一层目录,需要注意相对导入不能超过顶级包的界限

相对导入

相对导入,如果是入口文件那么不能使用相对路径,就是python 1.py,那么1.py不能使用相对导入,非入口文件可以随意使用相对导入,比如1.py中调用2.py,2.py就能用。

绝对导入与相对导入的区别

  1. -m属性执行可以在任何地方执行sys.path中的代码,因为他执行的是模块,模块的话只要在sys.path中就能找到并执行,如果是普通执行则只能执行当前文件夹,或指定路径的py文件。

  1. -m属性添加到sys.path的是执行脚本时的路径加入到path,普通是添加py文件的父文件夹

Python模块__all__变量以及导入可见性问题

需求:导入一个模块的所有变量,函数时,想选择性的允许外部导入自己的模块,有的可以让外部导入,有的我们不想让外部导入,此时用__all__可以做到

作用:唯一限制from demo import *能导入的东西(注意只能限制这一种方式)

事实上,当我们向文件导入某个模块时,导入的是该模块中那些名称不以下划线(单下划线“_”或者双下划线“__”)开头的变量、函数和类。因此,如果我们不想模块文件中的某个成员被引入到其它文件中使用,可以在其名称前添加下划线。

以前面章节中创建的 demo.py 模块文件和 test.py 文件为例(它们位于同一目录),各自包含的内容如下所示:

#demo.py
def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:http://c.biancheng.net")
def disPython():
    print("Python教程:http://c.biancheng.net/python")

#test.py
from demo import *
say()
CLanguage()
disPython()

执行 test.py 文件,输出结果为:

人生苦短,我学Python!
C语言中文网: http://c.biancheng.net
Python教程: http://c.biancheng.net/python

在此基础上,如果 demo.py 模块中的 disPython() 函数不想让其它文件引入,则只需将其名称改为 _disPython() 或者 __disPython()。修改之后,再次执行 test.py,其输出结果为:

人生苦短,我学Python!
C语言中文网: http://c.biancheng.net
Traceback (most recent call last):
File "C:/Users/mengma/Desktop/2.py", line 4, in <module>
disPython()
NameError: name 'disPython' is not defined

显然,test.py 文件中无法使用未引入的 disPython() 函数。

Python模块__all__变量

除此之外,还可以借助模块提供的 __all__ 变量,该变量的值是一个列表,存储的是当前模块中一些成员(变量、函数或者类)的名称。通过在模块文件中设置 __all__ 变量,当其它文件以“from 模块名 import *”的形式导入该模块时,该文件中只能使用 __all__ 列表中指定的成员。

也就是说,只有以“from 模块名 import *”形式导入的模块,当该模块设有 __all__ 变量时,只能导入该变量指定的成员,未指定的成员是无法导入的。

举个例子,修改 demo.py 模块文件中的代码:

def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:http://c.biancheng.net")
def disPython():
    print("Python教程:http://c.biancheng.net/python")
__all__ = ["say","CLanguage"]

可见,__all__ 变量只包含 say() 和 CLanguage() 的函数名,不包含 disPython() 函数的名称。此时直接执行 test.py 文件,其执行结果为:

人生苦短,我学Python!
C语言中文网: http://c.biancheng.net
Traceback (most recent call last):
File "C:/Users/mengma/Desktop/2.py", line 4, in <module>
disPython()
NameError: name 'disPython' is not defined

显然,对于 test.py 文件来说,demo.py 模块中的 disPython() 函数是未引入,这样调用是非法的。

再次声明,__all__ 变量仅限于在其它文件中以“from 模块名 import *”的方式引入。也就是说,如果使用以下 2 种方式引入模块,则 __all__ 变量的设置是无效的。

1) 以“import 模块名”的形式导入模块。通过该方式导入模块后,总可以通过模块名前缀(如果为模块指定了别名,则可以使用模快的别名作为前缀)来调用模块内的所有成员(除了以下划线开头命名的成员)。

仍以 demo.py 模块文件和 test.py 文件为例,修改它们的代码如下所示:

#demo.py
def say():
    print("人生苦短,我学Python!")
def CLanguage():
    print("C语言中文网:http://c.biancheng.net")
def disPython():
    print("Python教程:http://c.biancheng.net/python")
__all__ = ["say"]
#test.py
import demo
demo.say()
demo.CLanguage()
demo.disPython()

运行 test.py 文件,其输出结果为:

人生苦短,我学Python!
C语言中文网: http://c.biancheng.net
Python教程: http://c.biancheng.net/python

可以看到,虽然 demo.py 模块文件中设置有 __all__ 变量,但是当以“import demo”的方式引入后,__all__ 变量将不起作用。

2) 以“from 模块名 import 成员”的形式直接导入指定成员。使用此方式导入的模块,__all__ 变量即便设置,也形同虚设。

仍以 demo.py 和 test.py 为例,修改 test.py 文件中的代码,如下所示:

from demo import say
from demo import CLanguage
from demo import disPython
say()
CLanguage()
disPython()

运行 test.py,输出结果为:

人生苦短,我学Python!
C语言中文网: http://c.biancheng.net
Python教程: http://c.biancheng.net/python
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当您使用Python编写脚本时,如果您想要导入位于其他目录中的模块,您需要将该模块所在目录添加到Python模块搜索路径中。这可以通过使用sys模块中的path属性来实现。以下是一个示例: ```python import sys # 添加模块搜索路径 sys.path.append('/path/to/module') # 导入模块 import module ``` 在这个例子中,我们将模块所在的路径添加到sys.path中,然后使用import语句导入模块。添加模块搜索路径的方法可以让Python解释器在搜索模块时查找指定的目录,从而使我们可以成功导入位于其他目录中的模块。 ### 回答2: Pythonsys.path.append是一个很重要的操作,其作用是动态添加模块搜索路径,以便在程序中使用某些模块时,可以从指定的路径中寻找该模块。 在Python中,当我们引用某个模块时,Python会搜索一个叫做sys.path路径列表,来寻找该模块。这个列表可以通过sys.path.append来动态添加新的路径。如果在此列表中找不到该模块Python会抛出ImportError异常。 sys.path.append()可以在Python运行时动态添加指定目录到sys.path中,使Python程序在运行时能够查找该目录下的模块。这个方法是Python中非常常用的方法之一,它可以用于自定义模块的位置,让Python解释器在自定义的目录中查找模块sys.path.append()方法接受一个路径字符串作为参数,这个路径字符串可以是相对路径或绝对路径。当我们调用该方法添加新路径时,Python会自动将这个路径添加到sys.path列表的最后一个元素中,这样Python程序就可以在此路径中查找模块了。 值得注意的是,每个Python程序都有一个默认的sys.path列表,这个列表由Python安装时自动配置,它Python安装目录下的库路径Python标准库所在路径sys.path列表并不是可修改的,因此我们需要动态添加新路径。 总之,sys.path.append()方法是一个非常有用的方法,可以方便地添加新模块搜索路径,使Python程序可以访问新路径下的模块。在实际开发中,我们可以根据需要动态添加新路径,来满足不同的需求。 ### 回答3: `sys.path` 是Python的module search path,通过它可以找到模块(.py文件)所在的路径,从而使Python代码中能够正确地导入和使用这些模块Python在启动时会设置一组默认的搜索路径,在其中括了Python标准库、安装的第三方库以及当前目录。 `sys.path.append()` 是一种常见的修改`sys.path` 的方式,它可以将一个新的目录添加到`sys.path` 中,从而允许Python在这个目录中查找模块。使用 `sys.path.append()`,我们可以手动指定目录,这个目录可以括我们自己的Python代码和第三方库。 `sys.path.append()` 的语法非常简单,只需要传递一个字符串参数,即要添加的目录路径。例如,假设你的项目代码存放在目录 `/home/user/myproject` 中,你可以通过以下代码添加该目录到`sys.path`中: ``` import sys sys.path.append('/home/user/myproject') ``` 使用`sys.path.append()`添加目录到`sys.path`中并不是一个常见的做法,因为它有一些缺点。如果我们在多个地方都使用`sys.path.append()`添加目录,那么系统路径会变得很长,很难维护。此外,如果不小心添加了一个路径错误的目录,可能会导致Python在运行时无法找到需要的模块,这会让我们非常头痛。 相较于`sys.path.append()`,更好的做法是将Python代码和相关的第三方库集中到一个虚拟环境中,并将这个虚拟环境作为Python解释器的默认环境。这样,我们就可以方便地管理Python库依赖关系,同时也可以避免出现系统路径过长和目录错误的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值