如何使用Python相对导入?及如何在b.py中读取指定文本文件?
先明确一下给定的目录结构:
/billy/b.py /billy/var/text.txt /sally/s.py
还有你提供的现有代码:
s.py的代码:
import sys, os sys.path.append('..') from billy import b print('s.py - ' + os.path.dirname(sys.argv[0]))
b.py的代码:
import sys, os print('b.py - ' + os.path.dirname(sys.argv[0])) ag = open(os.path.dirname(sys.argv[0]) + '//var//text.txt').read()
1. 如何使用Python相对导入?
首先得明确:相对导入只适用于包结构中的模块,也就是说你的目录需要被Python识别为包,每个包目录下必须有__init__.py文件(可以是空文件)。
针对你的场景,要从sally/s.py导入billy/b.py,如果想用相对导入,需要做这几步:
- 在
/billy/和/sally/目录下都创建空的__init__.py文件,让这两个目录变成Python包 - 修改
s.py的导入代码为相对导入语法:import os, sys from ..billy import b print('s.py - ' + os.path.dirname(sys.argv[0]))
⚠️ 注意哦:相对导入不能直接运行脚本文件,比如你直接在/sally/目录下执行python s.py会报错,因为此时s.py是作为__main__模块运行的,Python不允许在主模块中使用相对导入。这种情况下,你需要从项目根目录(也就是包含billy和sally的父目录/)运行,比如执行python -m sally.s,这样Python会把sally.s作为模块导入,相对导入就能正常工作了。
你现在用的sys.path.append('..') + from billy import b属于绝对导入的变通方式,通过把上级目录加入Python的模块搜索路径,让Python能找到billy包,这种方式在直接运行脚本时更实用,不需要依赖包结构的严格要求。
2. 如何在b.py中读取/billy/var/text.txt的内容?
你现有代码的问题在于:sys.argv[0]获取的是调用脚本的路径,而不是b.py自身的路径。比如当你运行s.py时,sys.argv[0]是s.py的路径,os.path.dirname(sys.argv[0])得到的是/sally/,拼接后变成/sally//var//text.txt,自然找不到目标文件。
正确的做法是用__file__变量,它代表当前模块文件的绝对路径,不管b.py是被导入还是直接运行,__file__都会指向/billy/b.py。然后用os.path.join()来拼接路径(跨平台更友好,不用手动写//或/)。
修改后的b.py代码如下:
import sys, os print('b.py - ' + os.path.dirname(__file__)) # 获取b.py所在的目录 current_dir = os.path.dirname(__file__) # 拼接var/text.txt的路径 text_file_path = os.path.join(current_dir, 'var', 'text.txt') # 推荐用with语句打开文件,自动处理关闭 with open(text_file_path, 'r') as f: ag = f.read()
这样不管是直接运行b.py,还是通过s.py导入b,都能正确找到/billy/var/text.txt文件。
内容的提问来源于stack exchange,提问作者Rhys

