Python:跨文件夹模块调用中的路径问题

本文介绍Python中跨文件夹调用时,产生的相对路径问题和模块搜索路径问题。
1. 相对路径问题

 假定我们的文件结构如下:

myExperiments
	-> test_1
		-> test_1.py
		-> img.jpg
	-> test_2
		-> test_2.py

 并且test_1.py中有如下函数,即读取img.jpg文件并返回其是否为None(为None表示读取失败):

import cv2
def read_image():
    img = cv2.imread("img.jpg")
    return img is None  # 返回False表示读取图片成功,True则为失败

 我们使用下面的方法在test_2.py中调用该函数,并在PyCharm中运行得到如下结果:

from test_1.test_1 import read_image
print(read_image())

[Out]:
True

 得到的结果为True,表示我们读取到的图片为None,即图片路径发生了错误。具体地,我们在运行test_2.py时,当前路径是“xxx\myExperiments\test_2”,再加上test_1.py中图片的相对路径“img.jpg",读取图片的路径为”xxx\myExperiments\test_2\img.jpg“,这显然是一个无效的地址。
 我们可以在test_1.py和test_2.py中,分别加入下面的代码,来输出该文件夹所对应的路径:(也有人建议os.path.abspath(os.curdir)、os.getcwd()、sys.argv[0],但经过测试还是如下的代码更适用本问题)

import os
print(os.path.dirname(__file__))

 加入上述代码后再次运行test_2.py程序,可以打印出两个.py文件的路径:

D:/CV_Project/myExperiments/test_2
D:\CV_Project\myExperiments\test_1
True

 所以,解决办法也就有了,在test_1.py中利用上述代码将相对路径改为绝对路径即可:

test_1,py:
def read_image():
    img = cv2.imread(os.path.dirname(__file__) + "/img.jpg")
    return img is None

[Out]:
False
 问题1解决!
2. 模块搜索路径问题

 上述代码在PyCharm中运行得不错,但是当我们在控制台中运行时,会出现模块调用的错误:
在这里插入图片描述
 问题产生的原因是,在模块搜索路径中没有找到test_1/test_1.py模块。我们在test_2.py中加入如下代码,并分别在PyCharm和Console中运行,得到如下结果:

test_2.py
import sys
pprint(sys.path)
from test_1.test_1 import read_image
print(read_image())

[PyCharm Out]:
['D:\\CV_Project\\myExperiments\\test_2',
 'D:\\CV_Project\\myExperiments',
 'E:\\Python\\PyCharm 2019.2.5\\helpers\\pycharm_display',
 'E:\\Anaconda\\anaconda\\python37.zip',
 'E:\\Anaconda\\anaconda\\DLLs',
 'E:\\Anaconda\\anaconda\\lib',
 'E:\\Anaconda\\anaconda',
 'E:\\Anaconda\\anaconda\\lib\\site-packages',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pdfparanoia-0.0.16-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pycocotools-2.0-py3.7-win-amd64.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pyqt5_stylesheets-2.3.0-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32\\lib',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\Pythonwin',
 'E:\\Python\\PyCharm 2019.2.5\\helpers\\pycharm_matplotlib_backend']
False

[Console Out]:
['D:\\CV_Project\\myExperiments\\test_2',
 'E:\\Anaconda\\anaconda\\python37.zip',
 'E:\\Anaconda\\anaconda\\DLLs',
 'E:\\Anaconda\\anaconda\\lib',
 'E:\\Anaconda\\anaconda',
 'E:\\Anaconda\\anaconda\\lib\\site-packages',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pdfparanoia-0.0.16-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pycocotools-2.0-py3.7-win-amd64.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pyqt5_stylesheets-2.3.0-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32\\lib',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\Pythonwin']
Traceback (most recent call last):
  File "test_2/test_2.py", line 16, in <module>
    from test_1.test_1 import read_image
ModuleNotFoundError: No module named 'test_1'

 这里我们输出的sys.path是指定用于模块搜索路径的字符串列表(module search path; path[0] is the script directory, else ‘’)。我们可以看到,在PyCharm中的sys.path比Console多个’D:\CV_Project\myExperiments’,而test_1/test_1.py模块正是位于该路径下。也正是因此,PyCharm中依据此路径可以成功加载test_1模块,而在Console中不行。
 PyCharm这种设置是可以在 “File | Settings | Build, Execution, Deployment | Console | Python Console”中修改的:
在这里插入图片描述
 所以,解决这种问题的最直观的方法就是在sys.path中手动添加所需路径,本问题中将test_2.py代码按如下修改:

import os, sys
sys.path.insert(0, os.path.abspath(
                    os.path.join(
                        os.path.dirname(__file__), "../"))
)
print(sys.path)
from test_1.test_1 import read_image
print(read_image())

[Console Out]:
['D:\\CV_Project\\myExperiments',
 'D:\\CV_Project\\myExperiments\\test_2',
 'E:\\Anaconda\\anaconda\\python37.zip',
 'E:\\Anaconda\\anaconda\\DLLs',
 'E:\\Anaconda\\anaconda\\lib',
 'E:\\Anaconda\\anaconda',
 'E:\\Anaconda\\anaconda\\lib\\site-packages',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pdfparanoia-0.0.16-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pycocotools-2.0-py3.7-win-amd64.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pyqt5_stylesheets-2.3.0-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32\\lib',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\Pythonwin']
False

 这里sys.path.insert(0, xxx)是将’D:\CV_Project\myExperiments’路径插入到sys.path最前面,当然也可以使用os.path.append(xxx)将其插入到最后面。可以看到,采用这种方法后,在Console运行时的sys.path中加入了所需路径,并成功运行。
 当然,对于本场景,还有一种更简单有效的方法。“python -m 模块” 的方式是把模块直接当脚本来运行,此时自动把输入命令的目录加入到了sys.path中(而不把.py文件的路径加进去)。所以,我们保持test_2.py为如下内容,并在Console中用python -m 调用:

test_2.py
import sys
print(sys.path)
from test_1.test_1 import read_image
print(read_image())

[Console In]:
D:\CV_Project\myExperiments>python -m test_2.test_2

[Console Out]:
['D:\\CV_Project\\myExperiments',
 'E:\\Anaconda\\anaconda\\python37.zip',
 'E:\\Anaconda\\anaconda\\DLLs',
 'E:\\Anaconda\\anaconda\\lib',
 'E:\\Anaconda\\anaconda',
 'E:\\Anaconda\\anaconda\\lib\\site-packages',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pdfparanoia-0.0.16-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pycocotools-2.0-py3.7-win-amd64.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\pyqt5_stylesheets-2.3.0-py3.7.egg',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\win32\\lib',
 'E:\\Anaconda\\anaconda\\lib\\site-packages\\Pythonwin']
False

 我们可以看到,这里sys.path中自动加入了’D:\CV_Project\myExperiments’(而非’D:\CV_Project\myExperiments\test_2’)。注意这个路径是输入命令的地址,当我们改变输入命令的地址时,这个也会发生改变。

 问题2解决!

综上,我们介绍了跨文件夹模块调用时产生的两个路径问题。对于相对路径问题,提出了修改相对路径为绝对路径的解决方法;对于模块搜索路径问题,针对sys.path提出了两种解决方法。

欢迎交流!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值