Python导出PDF:Anaconda可运行VS报错求助
问题描述
在Anaconda环境的Jupyter中运行Python导出PDF的代码一切正常,但在Visual Studio中运行时出现多个错误:
TypeError: FPDF.set_font() missing 1 required positional argument: 'family'multi_cell不存在ln参数
相关代码
from fpdf import FPDF import pytz from datetime import datetime from tkinter import filedialog class PDF(FPDF): def footer(self): # 设置页脚位置 self.set_y(-10) # 设置字体大小 self.set_font('Arial', 'I', 8) # 添加页码 self.cell(0, 10, f'Page {self.page_no()}/{{nb}}', 0, 0, 'C') def create_table(self,table_data, title='', data_size = 10, title_size=12, align_data='L', align_header='L', cell_width='even', x_start='x_default',emphasize_data=[], emphasize_style=None, emphasize_color=(0,0,0)): default_style = self.font_style if emphasize_style == None: emphasize_style = default_style # 获取列宽 def get_col_widths(): col_width = cell_width if col_width == 'even': col_width = self.epw / len(data[0]) - 1 # 平均分配宽度(epw是页面有效宽度,不含边距) elif col_width == 'uneven': col_widths = [] # 遍历列,找出每列最宽单元格的宽度 for col in range(len(table_data[0])): longest = 0 for row in range(len(table_data)): cell_value = str(table_data[row][col]) value_length = self.get_string_width(cell_value) if value_length > longest: longest = value_length col_widths.append(longest + 4) # 加4作为内边距 col_width = col_widths elif isinstance(cell_width, list): col_width = cell_width else: col_width = int(col_width) return col_width if isinstance(table_data, dict): header = [key for key in table_data] data = [] for key in table_data: value = table_data[key] data.append(value) # 转置数据,让格式符合表格要求 data = [list(a) for a in zip(*data)] else: header = table_data[0] data = table_data[1:] line_height = self.font_size * 2.5 col_width = get_col_widths() self.set_font(size=title_size) # 获取表格的X起始位置(用于居中表格) if x_start == 'C': table_width = 0 if isinstance(col_width, list): for width in col_width: table_width += width else: table_width = col_width * len(table_data[0]) margin_width = self.w - table_width center_table = margin_width / 2 x_start = center_table self.set_x(x_start) elif isinstance(x_start, int): self.set_x(x_start) elif x_start == 'x_default': x_start = self.set_x(self.l_margin) # 生成PDF内容 self.set_font(size=10) self.multi_cell(0, 2, 'Bộ Giáo dục và Đào tạo', border=0, align='L', ln=3, max_line_height=self.font_size) self.ln(5) self.multi_cell(0, 2, 'Trường ', border=0, align='L', ln=3, max_line_height=self.font_size) self.ln(5) self.multi_cell(0, 2, 'Địa chỉ:', border=0, align='L', ln=3, max_line_height=self.font_size) self.ln(10) # 添加标题 self.set_font(size=15) if title != '': self.multi_cell(0, line_height, title, border=0, align='c', ln=3, max_line_height=self.font_size) self.ln(8) # 获取越南时区当前时间 tz_VN = pytz.timezone('Asia/Ho_Chi_Minh') datetime_VN = datetime.now(tz_VN) now_vn = datetime_VN.strftime("%d/%m/%Y") self.set_font(size=10) self.multi_cell(0, 2, f'Ngày: {now_vn}', border=0, align='r', ln=3, max_line_height=self.font_size) self.ln(10) self.set_font(size=data_size) # 添加表头 y1 = self.get_y() x_left = x_start if x_start else self.get_x() x_right = self.epw + x_left if not isinstance(col_width, list): if x_start: self.set_x(x_start) for datum in header: self.multi_cell(col_width, line_height, datum, border=0, align=align_header, ln=3, max_line_height=self.font_size) x_right = self.get_x() self.ln(line_height) y2 = self.get_y() self.line(x_left,y1,x_right,y1) self.line(x_left,y2,x_right,y2) # 添加表格数据 for row in data: if x_start: self.set_x(x_start) for datum in row: if datum in emphasize_data: self.set_text_color(*emphasize_color) self.set_font(style=emphasize_style) self.multi_cell(col_width, line_height, datum, border=0, align=align_data, ln=3, max_line_height=self.font_size) self.set_text_color(0,0,0) self.set_font(style=default_style) else: self.multi_cell(col_width, line_height, datum, border=0, align=align_data, ln=3, max_line_height=self.font_size) self.ln(line_height) else: if x_start: self.set_x(x_start) for i in range(len(header)): datum = header[i] self.multi_cell(col_width[i], line_height, datum, border=0, align=align_header, ln=3, max_line_height=self.font_size) x_right = self.get_x() self.ln(line_height) y2 = self.get_y() self.line(x_left,y1,x_right,y1) self.line(x_left,y2,x_right,y2) # 添加表格数据 for row in data: if x_start: self.set_x(x_start) for i in range(len(row)): datum = str(row[i]) if not isinstance(row[i], str) else row[i] adjusted_col_width = col_width[i] if datum in emphasize_data: self.set_text_color(*emphasize_color) self.set_font(style=emphasize_style) self.multi_cell(adjusted_col_width, line_height, datum, border=0, align=align_data, ln=3, max_line_height=self.font_size) self.set_text_color(0,0,0) self.set_font(style=default_style) else: self.multi_cell(adjusted_col_width, line_height, datum, border=0, align=align_data, ln=3, max_line_height=self.font_size) self.ln(line_height) y3 = self.get_y() self.line(x_left,y3,x_right,y3) # 生成PDF示例(需提前定义表格数据data) data = [ ["STT", "Tên", "Điểm"], ["1", "Nguyễn Văn A", "8.5"], ["2", "Trần Thị B", "9.0"] ] pdf = PDF() pdf.add_page() pdf.add_font('DejaVu', '', r'ttf\DejaVuSansCondensed.ttf', uni=True) pdf.set_font("DejaVu","",12) pdf.alias_nb_pages() pdf.create_table(table_data = data,title='Báo cáo', cell_width='uneven',x_start='C') filename = filedialog.asksaveasfilename(defaultextension='.pdf') if filename: pdf.output(filename, 'F')
解决方案
问题根源
两个环境的FPDF库版本不兼容:
- Jupyter环境安装的是fpdf2(新版库,API更灵活,支持省略
set_font的family参数、multi_cell的ln/max_line_height参数) - Visual Studio环境安装的是旧版fpdf(即fpdf1.x,API严格,缺少新版的参数支持)
修复步骤
- 统一库版本
在VS的Python环境中执行以下命令,卸载旧版并安装新版fpdf2:
pip uninstall -y fpdf pip install fpdf2
- 代码兼容检查
- 若
self.font_style报错,直接替换为default_style = ''(fpdf2默认字体样式为空字符串) - 确认字体文件路径正确,可改为绝对路径避免相对路径问题
- 确保安装了
pytz依赖:pip install pytz(Windows系统默认自带tkinter,Linux/macOS需单独安装时执行sudo apt-get install python3-tk或对应系统命令)
- 测试运行
重新在VS中运行代码,即可消除版本不兼容导致的错误。
内容的提问来源于stack exchange,提问作者Matt John
相关产品推荐
相关产品推荐

