导入函数中当前目录(./)的位置及包发布后的路径变化问题
问题说明
文件夹结构
main_folder/ ├─ sub_folder/ │ ├─ sub_file.py ├─ main_file.py
sub_file.py 代码
def read_data(): with open("./datafile.txt", "rb") as f: data = f.readlines() return data
疑问
- 当其他脚本导入
sub_file.py并调用read_data()时,datafile.txt该放在哪里?也就是执行函数时的当前目录(./)是哪个位置? - 将代码发布为Python包而非本地使用时,文件路径是否会发生变化?
解答
1. 本地使用时的文件位置
./代表的是你启动Python程序时所在的工作目录,不是sub_file.py所在的目录。举两个实际场景:
- 如果你在
main_folder目录下打开终端,运行python main_file.py,那当前工作目录就是main_folder,这时候datafile.txt必须放在main_folder里才能被找到。 - 如果你在电脑的
桌面目录下运行python /xxx/main_folder/main_file.py,那当前工作目录是桌面,datafile.txt得放到桌面才能被读取到。
这种写法的弊端很明显:文件位置完全取决于用户启动程序的路径,非常不稳定。如果想让datafile.txt固定和sub_file.py放在一起,应该修改代码,用__file__获取脚本自身的路径来拼接:
import os def read_data(): # 获取sub_file.py所在的绝对目录 script_dir = os.path.dirname(os.path.abspath(__file__)) # 拼接数据文件的完整路径 data_path = os.path.join(script_dir, "datafile.txt") with open(data_path, "rb") as f: data = f.readlines() return data
这样不管在哪个目录启动程序,都能精准找到和sub_file.py同目录的datafile.txt。
2. 发布为包后的路径变化
发布成正式Python包后,原来的./写法问题会被放大——用户可能在任意目录安装包并调用,./指向的是用户当前工作目录,根本找不到包内的文件。
正确的处理方式是把datafile.txt作为包的资源文件,有两种常用方案:
- 继续用上面的
__file__拼接路径,只要把datafile.txt和sub_file.py放在同一个包目录下,安装后依然能正确定位。 - 对于Python 3.9及以上版本,推荐用
importlib.resources模块读取包内资源,这是更规范的官方方案:from importlib.resources import read_binary from . import __name__ as package_name def read_data(): # 直接读取包内的datafile.txt资源 data = read_binary(package_name, "datafile.txt") return data.splitlines()
这种方式不需要关心文件的实际安装路径,Python会自动处理包资源的查找逻辑。
内容的提问来源于stack exchange,提问作者CutePoison
相关产品推荐
相关产品推荐

