在开始探索Python连接CAD实现自动化绘图之前,让我们先明确一下读懂本教程所需的技术及知识基础。
首先需要你熟练使用Python编程语言,其次,对于CAD软件,本教程将以常见的AutoCAD平台为例,但您至少需要对 CAD 的基本操作和绘图原理有初步的认识。了解如何创建、编辑图形对象,设置图层、颜色、线型等属性,以及保存和导出 CAD 图纸的基本流程。
以下是本文所使用的开发环境:
Python解释器:Python-3.13
集成开发环境:PyCharm
CAD软件:AutoCAD2026简体中文版
操作系统:Windows 11专业版
第三方库:pyautocad-0.2.0
如何阅读本文:本文先对第三方库pyautocad
进行介绍,然后以代码进行应用示例,你可以先阅读前面关于pyautocad
的介绍,在进行示例阅读,或者先阅读示例部分,结合示例去理解pyautocad
提供的属性和方法。
pyautocad
介绍pyautocad
提供了五个模块,在分别是:
api
:包含与 AutoCAD 应用程序进行交互和操作的主要接口和功能,包含一个Autocad
类。
types
:定义了在与 AutoCAD 交互中使用的数据类型和结构,包含一个Apoint
类。
utils
:包含一些实用工具函数,用于常见的操作或辅助功能。
contrib
:能够处理表格数据,并提供了将数据导入和导出为多种格式(如csv
、xls
、xlsx
(写入)、json
)的功能。
cache
:处理缓存相关的操作。
api
模块介绍该模块包含一个Autocad
类,在pyautocad
的初始化文件中已经导入,可以直接通过from pyautocad import Autocad
导入,包含以下属性和方法:
create_if_not_exists
:这是一个布尔型属性,用于决定当 AutoCAD 应用未运行时,是否创建新的实例。如果为 True
,则会创建;如果为 False
,则不会创建,并抛出异常。
visible
:布尔型属性,决定新创建的 AutoCAD 实例是否可见。如果为 True
,新实例可见;如果为 False
,新实例不可见。
#创建Autocad实例,建立与AutoCAD的连接
acad = Autocad(create_if_not_exists = True,visible = True)
名称 | 参数介绍 | 描述 |
---|---|---|
@property app(self) |
—— | 获取活动的 AutoCAD.Application 对象。如果当前未获取到且满足创建条件,会创建新的应用对象并返回。 |
@property doc(self) |
—— | 获取当前 AutoCAD.Application 对象的活动文档。 |
@property model(self) |
—— | 获取活动文档的模型空间。 |
iter_layouts(self, doc=None, skip_model=True) |
doc : 指定要迭代布局的文档对象,如果为 None ,则使用当前活动文档。 skip_model :布尔值,决定是否跳过模型空间(ModelSpace );如果为 False ,则不会跳过,会将模型空间也包含在迭代结果中。默认为 True 。 |
迭代指定文档(默认是当前活动文档)中的布局。可以选择是否跳过模型空间。 |
iter_objects(self, object_name_or_list=None, block=None, limit=None, dont_cast=False) |
- object_name_or_list :迭代对象名称或名称列表。如果提供了这个参数,方法会在迭代过程中根据对象的名称进行筛选,只返回名称匹配的对象。如果是单个字符串,会检查对象名称是否包含该字符串;如果是列表,则检查对象名称是否与列表中的任何一个字符串匹配。block :AutoCAD 中的块对象。指定要从其中迭代对象的块。如果未提供,默认使用当前活动文档的活动布局的块。limit :整数或 None 。用于限制返回的对象数量。如果提供了一个正整数,那么迭代在达到这个数量后就会停止。如果是 None (默认值),则没有数量限制,会迭代块中的所有对象。dont_cast :布尔值。决定是否获取对象的最佳接口。如果为 True ,不会获取最佳接口,可能会加快迭代速度,但返回的对象需要调用者自行处理类型转换。如果为 False (默认值),会获取对象的最佳接口。获取对象的最佳接口意味着尝试将返回的对象转换为最适合操作和访问其属性、方法的特定类型或接口。这样可以更方便和准确地对对象进行操作和获取其详细信息。 |
从指定的块(默认是当前活动布局的块)中迭代对象。可以根据对象名称或列表进行筛选,设置返回对象的数量限制,并选择是否获取对象的最佳接口。 |
iter_objects_fast(self, object_name_or_list=None, container=None, limit=None) |
object_name_or_list :对象名称或名称列表,用于筛选要迭代的对象。 container :类似于 block ,指定要迭代的容器。 limit :返回对象的最大数量限制,如果为 None ,则无限制。 |
iter_objects 方法的快捷方式,不获取对象的最佳接口,加快迭代速度,但不建议常规使用。 |
find_one(self, object_name_or_list, container=None, predicate=None) |
object_name_or_list :对象名称或名称列表,用于筛选要查找的对象。container :类似于 block ,指定查找的范围。predicate :一个可调用对象,用于定义更复杂的查找条件,如果为 None ,使用布尔值判断。 |
在对象迭代中查找第一个满足给定谓词的对象。如果未提供谓词,则使用默认的布尔值判断。 |
best_interface(self, obj) |
obj :要获取最佳接口的对象。 |
获取指定对象的最佳接口。 |
prompt(self, text) |
text :要打印的文本。 |
在控制台和 AutoCAD 提示符中打印指定的文本。 |
get_selection(self, text="Select objects") |
text :提示用户选择对象时显示的文本,默认为 "Select objects" 。 |
提示用户进行对象选择。包括打印选择提示、处理选择集的添加和删除操作,以及在屏幕上进行选择,并返回选择集对象。 |
aDouble 、aInt 、aShort |
—— | 静态方法,分别是 pyautocad.types 中相关函数的快捷方式,用于特定的数据类型转换。 |
types
模块介绍 该模块包含一个 Apoint
类,在 pyautocad
的初始化文件中已导入,可直接通过 from pyautocad import Apoint
来引入。此类别主要用于表示 3D 点,并提供了众多特殊方法(又称魔法方法),涵盖几何运算操作(如加、减、乘、除等)以及与其他数值或点的运算。此外,它还支持便捷的属性访问(如 x
、y
、z
坐标)。特殊方法因几乎不在外部调用,在这里不做介绍。
x
:获取或设置 3D 点的 x 坐标。
y
:获取或设置 3D 点的 y 坐标。
z
:获取或设置 3D 点的 z 坐标。
创建APoint
实例:
# 创建一个3D点实例
point3 = Apoint(10,10,10)
# 创建一个2D点实例
point2 = Apoint(10,10)
distance_to(self, other)
:其主要作用是计算当前 APoint
对象(即 self
所代表的点)与另一个点(由 other
参数表示)之间的距离。
other
:可以是一个Apoint
对象,也可以是包含3个坐标的序列(列表或元组)types
模块的方法distance(p1, p2)
是一个用于计算两个点之间距离的函数。
p1
、p2
:可以是 APoint
类的实例,或者是任何包含三个坐标值的序列(列表 [x1, y1, z1]
或元组 (x1, y1, z1)
)。utils
模块介绍 这是一个工具模块,主要提供了一些与 AutoCAD 中的文本处理、表格操作、计时和动态打印相关的实用函数和上下文管理器。以下是对其方法介绍:
名称 | 参数介绍 | 描述 |
---|---|---|
unformat_mtext(s, exclude_list=('P', 'S')) |
s :包含格式信息的多行文本字符串。exclude_list :一个包含不应被去除格式的标签字符的列表,默认为 ('P', 'S') 。 |
去除给定字符串中的特定格式信息,除了指定的标签。 |
mtext_to_string(s) |
s :包含格式信息的多行文本字符串。 |
去除格式信息,并将 \\P (段落)替换为换行符 |
string_to_mtext(s) |
s :普通字符串。 |
将普通字符串转换为 AutoCAD 多行文本格式。 |
text_width(text_item) : |
text_item :Text 或 MultiText 对象。 |
获取该文本对象的宽度。 |
@contextmanager suppressed_regeneration_of(table) |
table :表格对象。 |
上下文管理器,在上下文内抑制表格的重新生成,以提高操作效率。 |
@contextmanager timing(message=u'Elapsed') |
message :自定义的打印消息,默认为 'Elapsed' 。 |
上下文管理器,用于测量并打印上下文内操作的执行时间。 |
dynamic_print(text) |
text :要动态打印的文本。 |
在同一行动态更新打印的文本,常用于显示进度或类似的动态信息。 |
contrib
模块介绍 该模块包含两个类:一个是Table
,另一个是_TableImporter
。_TableImporter
是一个私有类,这里只介绍Table
的方法。
名称 | 参数 | 描述 |
---|---|---|
writerow(self,row) |
row :要添加的行数据,应为列表或元组。 |
将一行数据添加到表格中。 |
append(self,row) |
row :要添加的行数据,应为列表或元组。 |
与 writerow 方法相同,是其同义词。 |
clear(self) |
—— | 清空当前表格中的所有数据。 |
save(self,filename, fmt, encoding='cp1251') |
filename :保存数据的文件路径。fmt :保存的文件格式,如 'csv' 、'xls' 等。 encoding :'csv' 格式的编码,默认为 'cp1251' 。 |
将表格数据保存到指定格式的文件中。仅支持(csv 、xls 、xlsx 、 json ) |
convert(self,fmt) |
fmt :期望转换的数据格式。 |
将表格数据转换为指定的格式。 |
to_csv(stream, encoding='cp1251', delimiter=';', **kwargs) |
stream :写入数据的流对象。encoding :输出数据的编码,默认为 'cp1251' 。delimiter :csv 文件的分隔符,默认为 ';' 。kwargs :传递给 csv.writer 的其他参数。 |
将表格数据以 csv 格式写入指定的流。 |
@staticmethod data_from_file(filename, fmt=None, csv_encoding='cp1251', csv_delimiter=';') |
filename :包含数据的文件路径。fmt :指定的文件格式,如果为 None 则根据文件扩展名猜测。 csv_encoding :csv 数据的编码,默认为 'cp1251' 。csv_delimiter :csv 数据的分隔符,默认为 ';' 。 |
从指定的文件中读取数据,并根据指定的格式或文件扩展名猜测格式进行解析。 |
@staticmethod available_write_formats() |
—— | 返回可用的写入格式列表。 |
@staticmethod available_read_formats() |
—— | 返回可用的读取格式列表。 |
cache
模块介绍 该模块用于缓存所有对象属性的代理。提供了一个Cached
类用于缓存对象属性的代理类,该类提供了以下方法:
get_original(self)
:
switch_caching(self, is_enabled)
:
is_enabled
:布尔值,True
启用缓存,False
禁用缓存。from pyautocad import Autocad, APoint
# 连接到 AutoCAD,需要手动打开CAD并新建一个文档
acad = Autocad()
# 连接到AutoCAD,如果CAD没有启动,则启动CAD并使其可见
# acad = Autocad(create_if_not_exists=True,visible=True)
# 获取当前文档
doc = acad.doc
# 获取模型空间
model_space = doc.ModelSpace
# 在模型空间添加一个点
point = model_space.AddPoint(APoint(10, 10))
print(f"添加的点: {point.Coordinates}")
# 手动保存,退出
acad.app.Quit()
from pyautocad import Autocad, APoint
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
start_point = APoint(0, 0)
end_point = APoint(50, 50)
line = model_space.AddLine(start_point, end_point)
print(f"绘制的直线: 起点 {line.StartPoint}, 终点 {line.EndPoint}")
from pyautocad import Autocad, APoint
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
center = APoint(100, 100)
radius = 25
circle = model_space.AddCircle(center, radius)
print(f"绘制的圆: 圆心 {circle.Center}, 半径 {circle.Radius}")
from pyautocad import Autocad, APoint
def draw_polyline():
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
# 定义多段线的顶点
points = [APoint(0, 0), APoint(50, 0), APoint(50, 50), APoint(0, 50)]
# 创建多段线对象
polyline = model_space.AddPolyline([(point.x, point.y) for point in points])
# 设置多段线的宽度(可选操作)
polyline.SetWidth(0, 0, 2) # 起始宽度,结束宽度
print(f"绘制的多段线: 顶点数量 {polyline.NumberOfVertices}")
if __name__ == "__main__":
draw_polyline()
from pyautocad import Autocad, APoint
import math
def draw_arc():
# 创建Autocad对象,这将尝试连接到已运行的AutoCAD实例
acad = Autocad()
# 获取当前打开的文档
doc = acad.doc
# 获取模型空间,模型空间是我们绘制图形的主要区域
model_space = doc.ModelSpace
# 定义圆弧的圆心坐标,这里使用APoint类来表示一个点
center = APoint(100, 100)
# 定义圆弧的半径
radius = 50
# 定义圆弧的起始角度(以度为单位)
start_angle_degrees = 0
# 将起始角度从度转换为弧度,因为pyautocad中角度参数通常以弧度为单位
start_angle_radians = math.radians(start_angle_degrees)
# 定义圆弧的结束角度(以度为单位)
end_angle_degrees = 90
# 将结束角度从度转换为弧度
end_angle_radians = math.radians(end_angle_degrees)
# 在模型空间中添加圆弧
# AddArc方法的参数依次为圆心、半径、起始弧度、结束弧度
arc = model_space.AddArc(center, radius, start_angle_radians, end_angle_radians)
if __name__ == "__main__":
draw_arc()
from pyautocad import Autocad, APoint
def draw_ellipse():
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
# 定义椭圆中心
center = APoint(100, 100)
# 定义长轴端点,用于确定椭圆的长轴方向和长度
major_axis_end = APoint(150, 100)
# 定义短轴与长轴的比例
ratio = 0.6
# 在模型空间绘制椭圆
ellipse = model_space.AddEllipse(center, major_axis_end, ratio)
if __name__ == "__main__":
draw_ellipse()
from pyautocad import Autocad
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
# 遍历模型空间对象所有对象,请提前绘制一些直线,圆,点等
for obj in model_space:
print(f"对象类型: {obj.ObjectName}, 对象 ID: {obj.ObjectId}")
from pyautocad import Autocad
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
# 遍历模型空间的直线对象
for obj in model_space:
if obj.ObjectName == "AcDbLine":
print(f"直线: 起点 {obj.StartPoint}, 终点 {obj.EndPoint}")
下边列出一些模型空间的一些对象名称:
AcDbLine
:直线 AcDbCircle
:圆AcDbArc
:弧线AcDbPolyline
:多段线AcDbMText
:多行文字AcDbText
:单行文字AcDbEllipse
:椭圆AcDbSpline
:样条曲线AcDbRotatedDimension
:尺寸标注from pyautocad import Autocad, APoint
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
text_point = APoint(100, 100)
text_height = 5
text_string = "Hello, AutoCAD!"
text = model_space.AddText(text_string, text_point, text_height)
from pyautocad import Autocad, APoint
acad = Autocad()
doc = acad.doc
model_space = doc.ModelSpace
mtext_point = APoint(150, 150)
mtext_width = 50
mtext_string = "这是一个多行文本示例\n包含多行内容"
mtext = model_space.AddMText(mtext_point, mtext_width, mtext_string)
from pyautocad import Autocad
def get_existing_line_properties():
# 连接到AutoCAD应用程序,如果不存在则创建
acad = Autocad(create_if_not_exists=True)
doc = acad.doc
model_space = doc.ModelSpace
# 获取模型空间中的直线对象,首先你要绘制一条直线。
line = model_space.Item(0)
properties = {
'对象ID': line.ObjectID,
'颜色': line.Color,
'图层': line.Layer,
'长度': line.Length,
'起点': line.StartPoint,
'终点': line.EndPoint,
'厚度': line.Thickness,
'线型': line.Linetype,
'线宽': line.LineWeight
}
for prop, value in properties.items():
print(f"{prop}: {value}")
if __name__ == "__main__":
get_existing_line_properties()
from pyautocad import Autocad
def get_existing_circle_properties():
# 连接到AutoCAD应用程序,如果不存在则创建
acad = Autocad(create_if_not_exists=True)
doc = acad.doc
model_space = doc.ModelSpace
# 获取明星空间对象数量
if model_space.Count > 0:
entity = model_space.Item(0)
# 判断对象是否为圆对象
if entity.EntityName == 'AcDbCircle':
properties = {
'对象ID': entity.ObjectID,
'颜色': entity.Color,
'图层': entity.Layer,
'圆心': entity.Center,
'半径': entity.Radius,
'直径': entity.Diameter,
'周长': entity.Circumference,
'面积': entity.Area,
'厚度': entity.Thickness,
'线型': entity.Linetype,
'线宽': entity.LineWeight
}
for prop, value in properties.items():
print(f"{prop}: {value}")
else:
print("模型空间中的第一个对象不是圆")
else:
print("模型空间中没有对象")
if __name__ == "__main__":
get_existing_circle_properties()
from pyautocad import Autocad, APoint
def get_polyline_properties():
acad = Autocad(create_if_not_exists=True)
doc = acad.doc
model_space = doc.ModelSpace
for i in range(model_space.Count):
entity = model_space.Item(i)
if entity.EntityName in ['AcDbPolyline', 'AcDbLWPolyline']:
# 是否闭合
is_closed = entity.Closed
# 获取长度
length = entity.Length
# 获取面积
area = entity.Area if hasattr(entity, 'Area') else 'N/A'
# 获取颜色
color = entity.Color
# 获取图层
layer = entity.Layer
# 获取线型
linetype = entity.Linetype
# 获取线宽
lineweight = entity.LineWeight
print(f"多段线的闭合状态: {'闭合' if is_closed else '开放'}")
print(f"多段线的长度: {length}")
print(f"多段线的面积: {area}")
print(f"多段线的颜色: {color}")
print(f"多段线所在图层: {layer}")
print(f"多段线的线型: {linetype}")
print(f"多段线的线宽: {lineweight}")
if __name__ == "__main__":
get_polyline_properties()
from pyautocad import Autocad
def get_arc_properties():
acad = Autocad(create_if_not_exists=True)
doc = acad.doc
model_space = doc.ModelSpace
for i in range(model_space.Count):
entity = model_space.Item(i)
if entity.EntityName == 'AcDbArc':
# 圆心坐标
center = entity.Center
print(f"圆弧圆心坐标: {center}")
# 半径
radius = entity.Radius
print(f"圆弧半径: {radius}")
# 起始角度
start_angle = entity.StartAngle
print(f"圆弧起始角度: {start_angle}")
# 终止角度
end_angle = entity.EndAngle
print(f"圆弧终止角度: {end_angle}")
# 面积
area = entity.Area
print(f"圆弧面积: {area}")
# 长度
arclength = entity.ArcLength
print(f"圆弧长度: {arclength}")
# 颜色
color = entity.Color
print(f"圆弧颜色: {color}")
# 图层
layer = entity.Layer
print(f"圆弧所在图层: {layer}")
# 线型
linetype = entity.Linetype
print(f"圆弧线型: {linetype}")
# 线宽
lineweight = entity.LineWeight
print(f"圆弧线宽: {lineweight}")
if __name__ == "__main__":
get_arc_properties()
from pyautocad import Autocad, APoint
def get_ellipse_properties():
acad = Autocad(create_if_not_exists=True)
doc = acad.doc
model_space = doc.ModelSpace
for i in range(model_space.Count):
entity = model_space.Item(i)
if entity.EntityName == 'AcDbEllipse':
# 椭圆中心
center = entity.Center
print(f"椭圆中心坐标: {center}")
# 长轴端点
major_axis_end = entity.MajorAxis
print(f"椭圆长轴端点坐标: {major_axis_end}")
# 短轴比例因子
ratio = entity.RadiusRatio
print(f"椭圆短轴与长轴比例因子: {ratio}")
# 面积
area = entity.Area
print(f"椭圆面积: {area}")
# 颜色
color = entity.Color
print(f"椭圆颜色: {color}")
# 图层
layer = entity.Layer
print(f"椭圆所在图层: {layer}")
# 线型
linetype = entity.Linetype
print(f"椭圆线型: {linetype}")
# 线宽
lineweight = entity.LineWeight
print(f"椭圆线宽: {lineweight}")
if __name__ == "__main__":
get_ellipse_properties()