文章目录

  • part one: 文件在同一个文件夹
  • 1.函数调用
  • 2.类调用
  • part two:文件在不同文件夹
  • 1.在同一个目录
  • 2.在任意目录:绝对路径
  • 1.借助sys
  • 2.借助path
  • part three:更新,相对路径
  • attention: error
  • 导入模块
  • 导入文件



python导入模块有如下几种写法:以matplotlib为例


1,import matplotlib 

 2 , from matplotlib import * 

 3 , import matplotlib as ml


以上三种方法中建议第三种。因为第一种如果需要从matplotlib中使用其下的函数,如pyplot,则需要写成matplotlib.pyplot,很长,比较麻烦;而第二种在任何时刻都是不建议使用的,因为*表示导入了matplotlib中的所有函数,这样虽然使用pyplot的时候直接写成pyplot可以简写,但是如果matplotlib下的函数有函数名和其他定义的函数名相同的时候就会冲突导致报错;第三种是最好的,既可以简写也不过冲突,使用pyplot直接写成ml.pyplot

part one: 文件在同一个文件夹

1.函数调用

第一个为hello.py模块,内容为定义的一个函数:

def Hello():
    print('Hello world')

另一个文件为调用该文件的run.p文件,内容为:

import hello

h = hello.Hello()

记住Hello后有括号,当运行run.py文件,得到结果如下:

Hello world

以上为导入自定义模块的方法

2.类调用

如果将上面的hello.py改为:

def Hello():
        
        print('Hello world')

    def greeting():

        print('how are you')

将run.py写为

import hello
hello = hello.Hello()
greet = hello.greeting()

运行会报错:

AttributeError: 'NoneType' object has no attribute 'greeting'

此时我们需要将hello.py文件改为类,如下:

class Speak():
    def Hello():
        
        print('Hello world')

    def greeting():

        print('how are you')

调用的时候run.py为:

import hello

h = hello.Speak
hello = h.Hello()
greet = h.greeting()

part two:文件在不同文件夹

1.在同一个目录

如hello.py在文件夹test1下,而test1和run.py在同一个文件夹下,则导入时,只要将run.py改为:

from test1 import hello
'''
or
import test1.hello as th   #因为hello.py是位于test1文件夹下的,如果test1是文件
test.py, 而hello是test1.py下的类或函数则不能这么调用
h = th.Speak
'''
h = hello.Speak
hello = h.Hello()
greet = h.greeting()

上面代码中说的解释的那部分很关键,再次强调一下:
import matplotlib.pyplot as plt是因为matplotlib是一个文件夹,而pyplot是一个.py文件,所以可以直接用matplotlib.pyplot来调用,如果matplotlib是一个.py文件,而pyplot是它下面的一个函数或者类,则不能直接用点来调用,而要用

from matplotlib import pyplot
or
import matplotlib as pl
plt = matplotlib.pyplot()

2.在任意目录:绝对路径

以下1,2都是使用绝对路径

1.借助sys

总结:

import sys
sys.path.append('..') #表示导入当前文件的上层目录到搜索路径中
sys.path.append('/home/xxx') # 绝对路径
import os
sys.path.append(os.getcwd()) #		获取当前工作路径
#(注意:当前工作路径不一定是正在编辑的程序对应的路径)
#另外可以使用insert,这里不细说
sys.path.insert(1, "./xxx")

此时借助python内置函数sys放置路径
将run.py改为:(实际上sys里面的路径不需要写那么长,见part three)

import sys
sys.path.append('D:/software/python/note/testpy1/test1')

import hello

h = hello.Speak
hello = h.Hello()
greet = h.greeting()

例如导入上级模块,则只需要将上级模块的路径写出来,所以sys.path的作用是:当使用import语句导入模块时,解释器会搜索当前模块所在目录以及sys.path指定的路径去找需要import的模块,因此可以直接把上级目录加到sys.path里:sys.path.append(’…/’)

2.借助path

“这个方法原理就是利用了系统变量,python会扫描path变量的路径来导入模块”.在$python\Lib\site-packages目录下新建一个.pth的文件,如module_hello.pth,里面写上hello.py的路径,如:

D:\software\python\note\testpy1\test1

这个时候需要加载path,所以需要将run.py, hello.py以及IDLE编译器都重新打开,这个时候run.py只要写如下:

import hello

h = hello.Speak
hello = h.Hello()
greet = h.greeting()

补充:通常定义一个类我们需要初始化__init__,否则找不到属性(为空),这里只是简单的print(),不需要用到类的属性,可以查看文献为什么要用__init__:

part three:更新,相对路径

对于python模块的导入,可以使用绝对路径相对路径,使用官网文件举例如下:

python动态导入类 python导入类模块_ide


我们有一个文件夹sound(注意,一定要加__init__.py变成包,或者说初始化包,里面可以是空,因此下面我称为包),此包下面有三个包formats,effects,filters,(都有__init__.py)。现在我们在包effects下的surround.py文件,我们要在此文件下引用一些其他文件,则可以如下:

python动态导入类 python导入类模块_绝对路径_02


这里" . "表示当前路径,即跟surround.py一个文件夹下,“ … ”表示上一个路径,即跟effects一个文件夹。“ …filters ”指上个路径的filters文件夹。当然上面第一个等价于下面的绝对路径

import echo

而第二个则不能 from sound import formats 这个路径不对,此时想要绝对路径可以参考上面part two

attention: error

然而当笔者运行

from .. import formats

总会有下面的error: attempted relative import beyond top-level package
于是向师兄请教找到一个方法,即part two中的sys方法:

import sys
sys.path.append('../')

举例说明吧:

test
	 __init__.ppy
	 demo1
	 		__init__.py
	 		multiply.py
	 		sum_demo.py
	 		test1.py
	 demo2
	 	   __init__.py
	 	   divide.py
	 	   subtract.py
	 	   text.txt

举例

python动态导入类 python导入类模块_绝对路径_03


加载文件,其中文件位于当前代码的上一个文件夹中的data/CMB_rXXXX中。

导入模块

上面有一个文件夹test,其下有demo1和demo2两个包,分别执行两个数的加减乘除计算。现在我们test1.py里面调用demo2的divide.py里面的division()函数做除法运算,程序为:

import sys
sys.path.append('..')  # or('../')
import demo2.divide

print(demo2.divide.division(1,2))

结果是0.5:
这里append表示增加一个路径,…/代表此时路径的上一个文件夹。所以整体表示增加一个路径,且路径是C:\user…\test,即一直到test这个路径,所以test下有demo1和demo2.

导入文件

现在要在test1.ppy中导入demo2下的text.txt文件。

import numpy as np
file = np.loadtxt('../demo2/text.txt')   # 相对路径,../表示退出一层到test文件夹下,然后进入demo2文件夹

常见错误

上面可能有人想先整体导入demo2包,然后需要调用demo2包里面的函数的时候才使用demo2.divide,如下:

import sys
sys.path.append('..')
import demo2

print(demo2.divide.division(1,2))

error: module ‘demo2’ has no attribute ‘divide’

从error看出,我们没有成功导入divide.py文件,我们可以参考https://stackoverflow.com/questions/8899198/module-has-no-attribute;
出现错误的原因是实际上我们导入demo2的时候,demo2里面的.py文件,如divide.py并没有被自动导入,所以我们需要给出一个很具体的路径,如

import demo2.divide
print(demo2.divide.division(1,2))

当然也不能

import demo2.divide.division

因为divide是一个.py文件而不是一个包,所以不能这么再加具体的函数division
另外,如果我们实在想使用直接导入包demo2的形式,觉得这种形式比较方便,要使用哪个函数直接接.py文件的方法,那么我们就需要想办法把divide.py导进来,而这就是__init__.py的功劳。在demo2下面的__init__.py文件里面加入一句:

import demo2.divide

则可以正常运行

import sys
sys.path.append('..')
import demo2

print(demo2.divide.division(1,2))

结果是0.5
同理,我们要运行demo2.subtract.subtraction(1,2)需要在__init__.py里面写

import demo2.subtract