【python tkinter】0.1_通过阅读源码学习tkinterAPI_2026-05-12
0.1 通过阅读源码学习 tkinter API
开始编写于:2026-04-03 16:00
1.查看 tkinter 源码文件
本文使用 python 3.14.3 for windows 11。
python tkinter 源码文件位于以下位置:
python3.14.3/Lib/tkinter
tkinter 目录结构如下:
__pycache__/
colorchooser.py
commondialog.py
constants.py
dialog.py
dnd.py
filedialog.py
font.py
messagebox.py
scrolledtext.py
simpledialog.py
ttk.py
__init__.py
__main__.py
我们主要阅读 __init__.py 文件来学习 tkinter 的 API 。
掌握从零开始根据源码文件学习一个库的 API 后,目录里其他的源码文件也可以用类似方法来学习。
2.浏览__init__.py文件并了解API
接下来介绍几个可以快速了解一个 python 库全部 API 的方法。
- 打印
__all__变量 - 使用
dir()方法 - 使用
help()方法 - 使用
inspect.getmembers()方法 - 直接阅读源码
- 其他技术方法
2.1 打印 __all__ 变量
第一,可以通过打印 __all__ 变量的方式来查看开发者希望我们使用的 API 。
非常推荐使用这一方法!
在 Python 中,
__all__是一个特殊的模块级变量,定义了模块的公共接口。它是一个字符串列表,每个字符串对应变量、函数或类的名称,在使用 From module import * 语法导入模块时应导出这些变量。(来自bing)
python 3.14.3 关于
__all__的官方文档:7. 简单语句 —Python 3.14.3 文档一个模块所定义的 公有名称 是由在模块命名空间中检查名为
__all__的变量来确定的;如果有定义,它必须是一个字符串列表,其中的项为该模块所定义或导入的名称。 包含非 ASCII 字符的名称必须是 normalization form NFKC;详情参见 名称中的非 ASCII 字符。 在__all__中给出的名称都会被视为公有并且必须存在。 如果未定义__all__,则公有名称的集合将包括在模块的命名空间中找到的所有不以下划线字符 (‘_’) 打头的名称。__all__应当包含整个公有 API。 它的目标是避免意外地导出不属于 API 的组成部分的项(例如在模块内部被导入和使用的库模块)。
tkinter 在 __init__.py 第 5011 行定义了本库的 __all__ 变量。(截止 python 3.14.3)
__all__ = [name for name, obj in globals().items()
if not name.startswith('_') and not isinstance(obj, types.ModuleType)
and name not in {'wantobjects'}]
强烈推荐你尝试打印出这个变量来快速了解一个库的基本信息,可以在终端进行如下操作来打印 tkiner 的 __all__ 变量。
- 打开 Windows Terminal 终端
- 输入 python 打开 python 交互式命令行界面
- 导入 tkinter 并打印
tkinter.__all__
python
Python 3.14.3 (tags/v3.14.3:323c59a, Feb 3 2026, 16:04:56) [MSC v.1944 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
>>> print(tkinter.__all__)
然后我们可以得到 __all__ 变量的全部内容。
['TclError', 'NO', 'FALSE', 'OFF', 'YES', 'TRUE', 'ON', 'N', 'S', 'W', 'E', 'NW', 'SW', 'NE', 'SE', 'NS', 'EW', 'NSEW', 'CENTER', 'NONE', 'X', 'Y', 'BOTH', 'LEFT', 'TOP', 'RIGHT', 'BOTTOM', 'RAISED', 'SUNKEN', 'FLAT', 'RIDGE', 'GROOVE', 'SOLID', 'HORIZONTAL', 'VERTICAL', 'NUMERIC', 'CHAR', 'WORD', 'BASELINE', 'INSIDE', 'OUTSIDE', 'SEL', 'SEL_FIRST', 'SEL_LAST', 'END', 'INSERT', 'CURRENT', 'ANCHOR', 'ALL', 'NORMAL', 'DISABLED', 'ACTIVE', 'HIDDEN', 'CASCADE', 'CHECKBUTTON', 'COMMAND', 'RADIOBUTTON', 'SEPARATOR', 'SINGLE', 'BROWSE', 'MULTIPLE', 'EXTENDED', 'DOTBOX', 'UNDERLINE', 'PIESLICE', 'CHORD', 'ARC', 'FIRST', 'LAST', 'BUTT', 'PROJECTING', 'ROUND', 'BEVEL', 'MITER', 'MOVETO', 'SCROLL', 'UNITS', 'PAGES', 'TkVersion', 'TclVersion', 'READABLE', 'WRITABLE', 'EXCEPTION', 'EventType', 'Event', 'NoDefaultRoot', 'Variable', 'StringVar', 'IntVar', 'DoubleVar', 'BooleanVar', 'mainloop', 'getint', 'getdouble', 'getboolean', 'Misc', 'CallWrapper', 'XView', 'YView', 'Wm', 'Tk', 'Tcl', 'Pack', 'Place', 'Grid', 'BaseWidget', 'Widget', 'Toplevel', 'Button', 'Canvas', 'Checkbutton', 'Entry', 'Frame', 'Label', 'Listbox', 'Menu', 'Menubutton', 'Message', 'Radiobutton', 'Scale', 'Scrollbar', 'Text', 'OptionMenu', 'Image', 'PhotoImage', 'BitmapImage', 'image_names', 'image_types', 'Spinbox', 'LabelFrame', 'PanedWindow']
2.2 使用 dir() 方法
该方法与上一个打印 __all__ 变量的方法一样简单。
dir()函数 python3.14.3 官方文档:内置函数 —Python 3.14.3 文档如果没有实参,则返回当前本地作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。
如果对象有一个名为
__dir__()的方法,则该方法将被调用并且必须返回由属性组成的列表。这允许实现自定义__getattr__()或__getattribute__()函数的对象能够定制dir()报告其属性的方式。如果对象未提供
__dir__(),该函数会尽量从对象所定义的__dict__属性和其类型对象中收集信息。结果列表不一定是完整的,并且当对象具有自定义的__getattr__()时还可能是不准确的。默认的
dir()机制对不同类型的对象行为不同,它会试图返回最相关而不是最全的信息:
- 如果对象是模块对象,则列表包含模块的属性名称。
- 如果对象是类型或类对象,则列表包含它们的属性名称,并且递归查找所有基类的属性。
- 否则,列表包含对象的属性名称,它的类属性名称,并且递归查找它的类的所有基类的属性。
返回的列表按字母表排序。
备注:因为
dir()主要是为了便于在交互式时使用,所以它会试图返回人们感兴趣的名字集合,而不是试图保证结果的严格性或一致性,它具体的行为也可能在不同版本之间改变。例如,当实参是一个类时,metaclass 的属性不包含在结果列表中。
使用方法如下:
python
Python 3.14.3 (tags/v3.14.3:323c59a, Feb 3 2026, 16:04:56) [MSC v.1944 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
>>> print(dir(tkinter))
打印结果如下:
['ACTIVE', 'ALL', 'ANCHOR', 'ARC', 'BASELINE', 'BEVEL', 'BOTH', 'BOTTOM', 'BROWSE', 'BUTT', 'BaseWidget', 'BitmapImage', 'BooleanVar', 'Button', 'CASCADE', 'CENTER', 'CHAR', 'CHECKBUTTON', 'CHORD', 'COMMAND', 'CURRENT', 'CallWrapper', 'Canvas', 'Checkbutton', 'DISABLED', 'DOTBOX', 'DoubleVar', 'E', 'END', 'EW', 'EXCEPTION', 'EXTENDED', 'Entry', 'Event', 'EventType', 'FALSE', 'FIRST', 'FLAT', 'Frame', 'GROOVE', 'Grid', 'HIDDEN', 'HORIZONTAL', 'INSERT', 'INSIDE', 'Image', 'IntVar', 'LAST', 'LEFT', 'Label', 'LabelFrame', 'Listbox', 'MITER', 'MOVETO', 'MULTIPLE', 'Menu', 'Menubutton', 'Message', 'Misc', 'N', 'NE', 'NO', 'NONE', 'NORMAL', 'NS', 'NSEW', 'NUMERIC', 'NW', 'NoDefaultRoot', 'OFF', 'ON', 'OUTSIDE', 'OptionMenu', 'PAGES', 'PIESLICE', 'PROJECTING', 'Pack', 'PanedWindow', 'PhotoImage', 'Place', 'RADIOBUTTON', 'RAISED', 'READABLE', 'RIDGE', 'RIGHT', 'ROUND', 'Radiobutton', 'S', 'SCROLL', 'SE', 'SEL', 'SEL_FIRST', 'SEL_LAST', 'SEPARATOR', 'SINGLE', 'SOLID', 'SUNKEN', 'SW', 'Scale', 'Scrollbar', 'Spinbox', 'StringVar', 'TOP', 'TRUE', 'Tcl', 'TclError', 'TclVersion', 'Text', 'Tk', 'TkVersion', 'Toplevel', 'UNDERLINE', 'UNITS', 'VERTICAL', 'Variable', 'W', 'WORD', 'WRITABLE', 'Widget', 'Wm', 'X', 'XView', 'Y', 'YES', 'YView', '_VersionInfoType', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '_checkbutton_count', '_cnfmerge', '_debug', '_default_root', '_destroy_temp_root', '_exit', '_flatten', '_get_default_root', '_get_temp_root', '_join', '_magic_re', '_parse_version', '_print_command', '_setit', '_space_re', '_splitdict', '_stringify', '_support_default_root', '_test', '_tkerror', '_tkinter', '_varnum', 'collections', 'constants', 'enum', 'getboolean', 'getdouble', 'getint', 'image_names', 'image_types', 'mainloop', 're', 'sys', 'types', 'wantobjects']
2.3 使用 help() 方法
help() 方法是 python 的内置函数,是 python 官方推荐在交互式环境下对库进行探索的方法。
缺点是对于较大的模块,打印出的内容会非常多。
使用方法如下:
import tkinter
help(tkinter)
python
Python 3.14.3 (tags/v3.14.3:323c59a, Feb 3 2026, 16:04:56) [MSC v.1944 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
>>> help(tkinter)
Help on package tkinter:
NAME
tkinter - Wrapper functions for Tcl/Tk.
MODULE REFERENCE
https://docs.python.org/3.14/library/tkinter#module-tkinter
The following documentation is automatically generated from the Python
source files. It may be incomplete, incorrect or include features that
are considered implementation detail and may vary between Python
implementations. When in doubt, consult the module reference at the
location listed above.
DESCRIPTION
Tkinter provides classes which allow the display, positioning and
control of widgets. Toplevel widgets are Tk and Toplevel. Other
widgets are Frame, Label, Entry, Text, Canvas, Button, Radiobutton,
Checkbutton, Scale, Listbox, Scrollbar, OptionMenu, Spinbox
LabelFrame and PanedWindow.
Properties of the widgets are specified with keyword arguments.
Keyword arguments have the same name as the corresponding options
under Tk.
Widgets are positioned with one of the geometry managers Place, Pack
or Grid. These managers can be called with methods place, pack, grid
available in every Widget.
-- More --
2.4 使用 inspect.getmembers() 方法
使用该方法首先需要导入 inspect 库。
python 3.14.3
inspect.getmembers()方法相关官方文档:inspect — 检查活动对象 —Python 3.14.3 文档inspect.getmembers(object[, predicate])
返回一个对象上的所有成员,组成以 (名称, 值) 对为元素的列表,按名称排序。如果提供了可选的 predicate 参数(会对每个成员的 值 对象进行一次调用),则仅包含该断言为真的成员。备注:当参数是一个类且这些属性在元类的自定义方法
__dir__()中列出时getmembers()将只返回在元类中定义的类属性。
编写以下代码以查看 tkinter 库的指定内容:
import inspect
import some_lib
# 获取所有成员(名称-值对)
members = inspect.getmembers(some_lib)
# 按类型筛选:函数、类、模块等
functions = [name for name, val in members if inspect.isfunction(val)]
classes = [name for name, val in members if inspect.isclass(val)]
modules = [name for name, val in members if inspect.ismodule(val)]
print("Functions:", functions)
print("Classes:", classes)
print("Submodules:", modules)
输出结果为:
Functions: ['NoDefaultRoot', 'Tcl', '_cnfmerge', '_destroy_temp_root', '_exit', '_get_default_root', '_get_temp_root', '_join', '_parse_version', '_print_command', '_splitdict', '_stringify', '_test', '_tkerror', 'getboolean', 'image_names', 'image_types', 'mainloop']
Classes: ['BaseWidget', 'BitmapImage', 'BooleanVar', 'Button', 'CallWrapper', 'Canvas', 'Checkbutton', 'DoubleVar', 'Entry', 'Event', 'EventType', 'Frame', 'Grid', 'Image', 'IntVar', 'Label', 'LabelFrame', 'Listbox', 'Menu', 'Menubutton', 'Message', 'Misc', 'OptionMenu', 'Pack', 'PanedWindow', 'PhotoImage', 'Place', 'Radiobutton', 'Scale', 'Scrollbar', 'Spinbox', 'StringVar', 'TclError', 'Text', 'Tk', 'Toplevel', 'Variable', 'Widget', 'Wm', 'XView', 'YView', '_VersionInfoType', '_setit', 'getdouble', 'getint']
Submodules: ['_tkinter', 'collections', 'constants', 'enum', 're', 'sys', 'types']
2.5 直接阅读源码
使用 IDE 打开 __init__.py 代码文件,然后按 ctrl + f 搜索 def , class 等关键字来阅读浏览。
建议在浏览时做一些笔记,可以记在电子笔记里(markdown 、 LaTeX 或 word 等任何你喜欢的格式),甚至是记在纸质笔记本上都可以。
人的大脑的瞬时记忆只有15~30秒,如果不依赖外部介质来弥补人脑“RAM”记忆丢失快的缺点的话,你的开发体验会非常的糟糕!每次你想调用一个方法都需要被迫中断手上的编程工作去查阅资料文档,是会很大程度上降低编程效率和体验的!
也推荐你在开始任何稍有难度的项目前,通过笔记做好项目规划。
2.6 其他技术方法
以下方法仅给出思路,只属于理论上应该可行的办法,实操起来可能会较麻烦或有些难度。
- 使用 pydoc 库,生成完整文档。该方案更适合阅读,但没有
help()方法的交互性和易用性。另外help()方法也是基于 pydoc 库的。 - 使用 pkgutil 、 importlib 等库对导入的库进行深度递归和扫描,最终输出收集到的由浅到深的 API 信息。
- 使用 python ast 库解析指定 python 代码文件,通过抽象语法树 ast 提取可能的 API 信息。该方法要求对编译原理和python解释器工作原理有一定的熟练度。
END
结束编辑于:2026-04-03 21:00
状态:可发布
更新
开始编辑于:2026-04-18 16:30
print() 方法查看函数复杂参数 **kw 的使用方式(仅适用于 tkinter 库)
在 tkinter 的源码阅读和开发过程中,我们经常会遇到这样的情况:我们想要查看一个控件的参数设置,结果我们翻阅到对应 class 类时,只能看到这样的函数:(以 Lable 控件为例)
# 3371行 -> 3392行
class Label(Widget):
"""Label widget which can display text and bitmaps."""
def __init__(self, master=None, cnf={}, **kw):
"""Construct a label widget with the parent MASTER.
STANDARD OPTIONS
activebackground, activeforeground, anchor,
background, bitmap, borderwidth, cursor,
disabledforeground, font, foreground,
highlightbackground, highlightcolor,
highlightthickness, image, justify,
padx, pady, relief, takefocus, text,
textvariable, underline, wraplength
WIDGET-SPECIFIC OPTIONS
height, state, width
"""
Widget.__init__(self, master, 'label', cnf, kw)
# class Label 定义结束。
在这里会遇到一个比较奇怪的函数参数:**kw。在 Python 中,**kw 是用于函数定义中的关键字参数。它允许你传入任意数量的关键字参数,这些参数在函数内部会被自动组装成一个字典。
如果只看 __init__ 函数的参数名,我们是很难弄明白 **kw 这个参数是怎样使用的(虽然三引号内的Docstring为我们透露了不少信息,但这仅仅是注释文档性质的信息)。
如果我们继续追踪该参数的去向,比如查看 Label 的父类 Widget 的信息,也不一定保证真的能找到 **kw 的准确描述,甚至最后追溯的结果是一个来自二进制文件的函数调用,它会隐去各种细节,其中就包括我们想知道的 **kw 参数的具体可用键值对格式。(注:在 __init__.py 中确实追溯不到 **kw 的最终细节,追溯到最后会发现参数直接交给了二进制文件 _tkinter.pyd 的函数调用。详细追溯推导过程可以看未来后续更新的教程。)
这里我们使用一个更简单一些的方法,来避免掉进代码追溯的兔子洞里。我们直接使用 print() 方法查看 config() 函数来输出详细信息。在交互式 python 环境中输入以下代码:
import tkinter
root = tkinter.Tk()
btn = tkinter.Button(root) # 创建一个按钮实例
print(btn.config()) # 打印出所有可配置的属性
!【注意】:这种 print(btn.config()) 查看具体参数的做法,并不是通用的,这只是 tkinter 库的一个优秀设计。当你尝试对其他python函数使用该方法时,它不会像 tkinter 库的 print(btn.config()) 一样工作。
想要查看所有 python 函数的具体参数,只能使用我们在开头讲到的那些方法。而且你几乎在任何情况下都会被 **kw 拦住,无法进一步查看细节信息。除非你亲自阅读源码,弄清 **kw 参数的处理过程。
得到输出信息:(已进行格式整理)
{
'activebackground': ('activebackground', 'activeBackground', 'Foreground', <border object: 'SystemButtonFace'>, 'SystemButtonFace'),
'activeforeground': ('activeforeground', 'activeForeground', 'Background', <color object: 'SystemButtonText'>, 'SystemButtonText'),
'anchor': ('anchor', 'anchor', 'Anchor', <index object: 'center'>, 'center'),
'background': ('background', 'background', 'Background', <border object: 'SystemButtonFace'>, 'SystemButtonFace'),
'bd': ('bd', '-borderwidth'),
'bg': ('bg', '-background'),
'bitmap': ('bitmap', 'bitmap', 'Bitmap', '', ''),
'borderwidth': ('borderwidth', 'borderWidth', 'BorderWidth', 2, 2),
'command': ('command', 'command', 'Command', '', ''),
'compound': ('compound', 'compound', 'Compound', <index object: 'none'>, 'none'),
'cursor': ('cursor', 'cursor', 'Cursor', '', ''),
'default': ('default', 'default', 'Default', <index object: 'disabled'>, 'disabled'),
'disabledforeground': ('disabledforeground', 'disabledForeground', 'DisabledForeground', <color object: 'SystemDisabledText'>, 'SystemDisabledText'),
'fg': ('fg', '-foreground'),
'font': ('font', 'font', 'Font', <font object: 'TkDefaultFont'>, 'TkDefaultFont'),
'foreground': ('foreground', 'foreground', 'Foreground', <color object: 'SystemButtonText'>, 'SystemButtonText'),
'height': ('height', 'height', 'Height', 0, 0),
'highlightbackground': ('highlightbackground', 'highlightBackground', 'HighlightBackground', <border object: 'SystemButtonFace'>, 'SystemButtonFace'),
'highlightcolor': ('highlightcolor', 'highlightColor', 'HighlightColor', <color object: 'SystemWindowFrame'>, 'SystemWindowFrame'),
'highlightthickness': ('highlightthickness', 'highlightThickness', 'HighlightThickness', 1, 1),
'image': ('image', 'image', 'Image', '', ''),
'justify': ('justify', 'justify', 'Justify', <index object: 'center'>, 'center'),
'overrelief': ('overrelief', 'overRelief', 'OverRelief', '', ''),
'padx': ('padx', 'padX', 'Pad', 1, 1),
'pady': ('pady', 'padY', 'Pad', 1, 1),
'relief': ('relief', 'relief', 'Relief', <index object: 'raised'>, 'raised'),
'repeatdelay': ('repeatdelay', 'repeatDelay', 'RepeatDelay', 0, 0),
'repeatinterval': ('repeatinterval', 'repeatInterval', 'RepeatInterval', 0, 0),
'state': ('state', 'state', 'State', <index object: 'normal'>, 'normal'),
'takefocus': ('takefocus', 'takeFocus', 'TakeFocus', '', ''),
'text': ('text', 'text', 'Text', '', ''),
'textvariable': ('textvariable', 'textVariable', 'Variable', '', ''),
'underline': ('underline', 'underline', 'Underline', -1, -1),
'width': ('width', 'width', 'Width', 0, 0),
'wraplength': ('wraplength', 'wrapLength', 'WrapLength', 0, 0)
}
这是python中的某个特性吗?print() 一个函数名,就能返回它的参数细节?其实函数 btn.config() 只是在参数为空时,返回了一个记录着函数参数格式信息的字典,这只是 tkinter 库里的一个人为设计。如果你对其他函数使用这个方法,print() 只会像往常的预期一样返回函数的返回值。
对以上信息整理成表格:(表格来源:print(btn.config()),描述文本部分由 ai(deepseek)整理)
| 属性名 | 作用说明 |
|---|---|
activebackground | 鼠标悬停时按钮的背景色 |
activeforeground | 鼠标悬停时按钮的前景色(文字颜色) |
anchor | 文本/图像在按钮内的对齐方式(如 'center', 'nw') |
background / bg | 按钮的背景色(未激活状态) |
bitmap | 在按钮上显示的位图(如 'error', 'info'),与 image 互斥 |
borderwidth / bd | 边框宽度(像素) |
command | 按钮被点击时调用的函数或方法 |
compound | 文本与图像同时显示时的相对位置('top', 'left', 'center' 等) |
cursor | 鼠标悬停时的光标样式(如 'hand2', 'cross') |
default | 按钮作为“默认”按钮时的状态('normal', 'active', 'disabled') |
disabledforeground | 按钮禁用时文字的颜色 |
font | 按钮上文本的字体(如 ('Arial', 12)) |
foreground / fg | 按钮的前景色(文字颜色,未激活状态) |
height | 按钮的高度(单位:文本行数或像素,取决于 width 单位) |
highlightbackground | 按钮获得焦点时,高亮边框的背景色 |
highlightcolor | 按钮获得焦点时,高亮边框的颜色 |
highlightthickness | 高亮边框的厚度(像素) |
image | 在按钮上显示的图像(PhotoImage 或 BitmapImage 对象) |
justify | 多行文本的对齐方式('left', 'center', 'right') |
overrelief | 鼠标悬停时的边框浮雕效果(如 'raised', 'sunken') |
padx | 按钮内部文本/图像在水平方向上的额外间距(像素) |
pady | 按钮内部文本/图像在垂直方向上的额外间距(像素) |
relief | 边框的浮雕样式('flat', 'raised', 'sunken', 'ridge', 'solid') |
repeatdelay | 长按按钮时,开始重复触发 command 的延迟时间(毫秒) |
repeatinterval | 长按按钮时,两次重复触发之间的间隔(毫秒) |
state | 按钮的状态('normal', 'disabled', 'active') |
takefocus | 是否允许通过 Tab 键获得焦点(布尔值或空字符串) |
text | 按钮上显示的文本 |
textvariable | 与按钮文本关联的 Tkinter 变量(StringVar),可动态更新文本 |
underline | 文本中第几个字符加下划线(用于键盘快捷键,从 0 开始) |
width | 按钮的宽度(单位:文本字符数或像素) |
wraplength | 文本自动换行的最大长度(像素),0 表示不换行 |
UPDATE END
结束编辑时间:2026-04-18 20:00
状态:可发布
更多推荐
所有评论(0)