You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python自制IDE实现文件树遇FileNotFoundError,求修复方案

问题描述

用Python结合Tkinter开发IDE趣味项目,实现VS Code风格文件树功能时遇到问题:点击文件树中的文件会报错FileNotFoundError: [Errno 2] No such file or directory: './file.py',推测是程序在主文件所在目录查找目标文件,而非文件实际所在目录。

原代码如下:

########################################
#TREE
########################################
file_tree = Frame(root)
file_tree.pack(side='left', fill=Y, expand=NO)
def open_dir():
    for i in tree.get_children():
        tree.delete(i)
    path = askdirectory()
    abspath = os.path.abspath(path)
    root_node = tree.insert('', 'end', text=abspath, open=True)
    process_directory(root_node,abspath)

def process_directory( parent, path):

        for p in os.listdir(path):
            abspath = os.path.join(path, p)
            isdir = os.path.isdir(abspath)
            oid = tree.insert(parent, 'end', text=p, open=False)
            if isdir:
                process_directory(oid, abspath)

def Open_file_from_list_box(value):
    global file
    item_id = tree.selection()
    file = tree.item(item_id, 'text') # get the filename from 'text' option
    filepath = os.path.join(value,file)     
    editArea.delete(1.0,END)
    with open(filepath,"r") as f:
        editArea.insert(1.0,f.read())

tree = ttk.Treeview(file_tree)
tree.pack(expand=YES,fill=BOTH)
path = '.'
tree.heading('#0', text=path, anchor='w')
abspath = os.path.abspath(path)
root_node = tree.insert('', 'end', text=abspath, open=True)
process_directory(root_node, abspath)

tree.bind("<<TreeviewSelect>>",lambda event=None:Open_file_from_list_box(path))
问题根源
  • 绑定事件时传入的path始终是初始值.,并非选中文件所在的实际目录
  • tree.item(item_id, 'text')仅获取文件名/目录名,未保留完整路径信息,拼接后的路径指向主文件目录而非文件真实位置
修复方案

方法一:存储完整路径到Treeview节点(推荐)

修改代码,在插入Treeview节点时将文件/目录的完整路径存入values属性,打开文件时直接读取该值:

  1. 修改process_directory函数:
def process_directory(parent, path):
    for p in os.listdir(path):
        abspath = os.path.join(path, p)
        isdir = os.path.isdir(abspath)
        # 插入节点时存入完整路径到values
        oid = tree.insert(parent, 'end', text=p, open=False, values=(abspath,))
        if isdir:
            process_directory(oid, abspath)
  1. 修改Open_file_from_list_box函数:
def Open_file_from_list_box(event=None):
    item_id = tree.selection()
    # 从values中取出完整路径
    filepath = tree.item(item_id, 'values')[0]
    # 仅处理文件,避免点击目录报错
    if os.path.isfile(filepath):
        editArea.delete(1.0, END)
        with open(filepath, "r") as f:
            editArea.insert(1.0, f.read())
  1. 更新open_dir和初始节点插入代码,同样存入完整路径:
# open_dir函数内的root_node插入
root_node = tree.insert('', 'end', text=abspath, open=True, values=(abspath,))

# 初始root_node插入
root_node = tree.insert('', 'end', text=abspath, open=True, values=(abspath,))
  1. 修改事件绑定:
tree.bind("<<TreeviewSelect>>", Open_file_from_list_box)

方法二:递归拼接父节点路径

若不想存储额外属性,可通过递归获取父节点的文本拼接出完整路径:

  1. 添加路径拼接函数:
def get_full_path(item_id):
    path = tree.item(item_id, 'text')
    parent_id = tree.parent(item_id)
    while parent_id:
        parent_path = tree.item(parent_id, 'text')
        path = os.path.join(parent_path, path)
        parent_id = tree.parent(parent_id)
    return os.path.abspath(path)
  1. 修改Open_file_from_list_box函数:
def Open_file_from_list_box(event=None):
    item_id = tree.selection()
    filepath = get_full_path(item_id)
    if os.path.isfile(filepath):
        editArea.delete(1.0, END)
        with open(filepath, "r") as f:
            editArea.insert(1.0, f.read())
  1. 修改事件绑定:
tree.bind("<<TreeviewSelect>>", Open_file_from_list_box)

注:方法二需确保所有节点的text都是正确的路径片段,若存在重命名显示等场景,可能出现路径错误,推荐使用方法一。

内容的提问来源于stack exchange,提问作者some_dude

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 06:35:43