Reportlab Layouterror: كبير جدا في الصفحة
-
12-09-2019 - |
سؤال
أقوم بعمل برنامجي الأول باستخدام ReportLab حيث لا أعرف مقدما حيث ستقع فواصل الصفحات وأواجه مشكلة. للحفاظ على الأشياء بسيطة أنا أستخدم SimpleDocTemplate
. وبعد تبدو واضحة بلدي شيء مثل هذا:
flowables = [Paragraph("Some title", style=headerParagraphStyle),
Spacer(0, 10),
Paragraph("first paragraph", style=bodyParagraphStyle),
Paragraph("second paragraph", style=bodyParagraphStyle),
...
Paragraph("nth paragraph", style=bodyParagraphStyle),
PageBreak(),
Paragraph("Some title", style=headerParagraphStyle),
Spacer(0, 10),
Paragraph("first paragraph", style=bodyParagraphStyle),
Paragraph("second paragraph", style=bodyParagraphStyle),
...
Paragraph("mth paragraph", style=bodyParagraphStyle),
PageBreak(),
...]
عندما أبني PDF، كل شيء على ما يرام طالما بلدي n
أو m
أو مهما تناسب العديد من الفقرات في الجسم على صفحة واحدة، ولكن إذا هربوا، فاحصل على خطأ مثل ما يلي:
reportlab.platypus.doctemplate.LayoutError: Flowable <Paragraph at 0xb79800 frame=normal>20th paragraph: too large on page 3
لا يمكن أن يبدو أن تجد سبب وجيه عن سبب حدوث ذلك لي. أي اقتراحات؟ يفعل هذا حتى لو قمت بإزالة الصفحات (). جميع الفقرات قصيرة نسبيا، معظمها أقل من جملة واحدة / خط عبر.
إيتا: أنا نشر كل الكود (مع محرز معرفات بسيطة) التي تولد الخطأ بالنسبة لي. لقد قمت بتحويلها لقراءة ملف CSV، لذلك قمت بنشر محتوياتها أيضا. الخطأ الدقيق الذي ينشئ هذا الرمز لي عندما أركض هو:
Traceback (أحدث المكالمة الأخيرة): ملف "./spice_dev.py"، السطر 355، في departmentreportdoc.build (everydepartment.report، onfirstpage = onfirpage، onlaterpages = onfortpage = onreportpage) ملف "/usr/local/lib/python2.6/ حزم الموقع / Reportlab / Platypus / doctemplate.py "، الخط 1010، في بناء المساد البناءة .BUILD (الذاتي، قابلية التدليك، canvasmaker = canvasmaker) ملف" /usr/local/lib/pothon2.6/site-packages/reportlab/platypus /Doctemplate.py "، خط 777، في Build Self.handle_Flowable (Selfableable) ملف" /usr/local/lib/packages/packages/reportlab/platypus/doctemplate.py "، السطر 694، في مقبض RIVER (التعريف) Reportlab.platypus.doctemplate.layouterror: تعليقات واقتراحات واضحة للتدفق للتحسين: كبير جدا في الصفحة 3
يوضح بعض أعمال التصحيح أن الخطأ هو نتيجة لهذه الفقرة (على الرغم من أنه يمكن أن تكون قابلة للتطول الأخرى، اعتمادا على طول المحتوى) في محاولة تقسيمها، وإنقاجها، ثم لا تزال غير قادرة على الانقسام بعد المكالمة handle_frameEnd()
. وبعد اقتراحات؟
Spice.py:
#!/usr/local/bin/python
# vim: set fileencoding=latin-1
#import csv
import os
import os.path
import time
import numpy
import scipy.stats._support
#for debugging
import sys
import traceback
# imports for reportlab
from reportlab.platypus import *
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.pagesizes import LETTER, landscape, portrait
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.pdfgen import canvas
from reportlab.lib.enums import *
##########################
####### Constants ########
##########################
kNumberOfQuestions = 4
##########################
####### Reportlab ########
##########################
def _doNothing(canv, doc):
pass
headerParagraphStyle = ParagraphStyle("Header", fontName="Helvetica-Bold", fontSize=16, spaceAfter = .05*inch, alignment=TA_CENTER)
header2ParagraphStyle = ParagraphStyle("Header2", fontName="Helvetica-Bold", fontSize=14, spaceAfter = .1*inch, spaceBefore=.5*inch, alignment=TA_CENTER)
subheaderInfoParagraphStyle = ParagraphStyle("Subheader Info", fontName="Helvetica-Bold", fontSize=10, alignment=TA_CENTER)
questionParagraphStyle = ParagraphStyle("Question header", fontName="Helvetica-Bold", fontSize = 10, alignment=TA_LEFT)
commentParagraphStyle = ParagraphStyle("Comment", fontName="Helvetica", fontSize = 10, alignment=TA_LEFT)
instructorParagraphStyle = ParagraphStyle("Instructor Header", fontName="Helvetica", fontSize=10, alignment=TA_LEFT)
basicTableStyle = TableStyle(
[('FONT', (0, 0), (-1, 0), 'Helvetica-Bold', 9),
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
('LINEBELOW', (0, 0), (-1, 0), 1, colors.black),
('INNERGRID', (0, 0), (-1, 0), 1, colors.black),
('FONT', (0, 1), (-1, -1), 'Helvetica', 9),
('ALIGN', (0, 1), (-1, 1), 'LEFT'),
('ALIGN', (1, 1), (-1, -1), 'CENTER'),
('LINEAFTER', (0, 1), (0, -1), 1, colors.black),
('LINEBEFORE', (1, 1), (-1, -1), 1, colors.black),
('ROWBACKGROUNDS', (0, 1), (-1, -1), (colors.white, (.9, .9, .9))),
('TOPPADDING', (1, 1), (-1, -1), 8)
])
statTableStyle = TableStyle(
[('FONT', (0, 0), (0, -1), 'Helvetica-Bold', 9),
('ALIGN', (0, 0), (0, -1), 'RIGHT'),
('INNERGRID', (0, 0), (-1, -1), 1, colors.black),
('FONT', (1, 0), (1, -1), 'Helvetica', 9),
('ALIGN', (1, 0), (1, -1), 'LEFT')
])
headerTableStyle = TableStyle(
[('FONT', (0, 0), (-1, 0), 'Helvetica', 8),
('FONT', (0, 1), (-1, 1), 'Helvetica-Bold', 8),
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
('LINEBELOW', (0, 0), (-1, 0), 1, colors.black),
('LINEAFTER', (0, 0), (-1, -1), 20, colors.white),
('LEFTPADDING', (0,0), (-1, -1), 15),
('RIGHTPADDING', (0, 0), (-1, -1), 15)
])
##########################
######## Classes #########
##########################
class Course:
def __init__(self):
self.prefix = ""
self.number = ""
self.section = ""
self.instructor = ""
self.email = ""
self.name = "None Found"
self.enrollment = 0
self.semester = ""
self.report = [] # subreport for the course
self.dataFile = []
def __repr__(self):
return self.prefix + " " + self.number + " " + self.section + " " + self.instructor
class Instructor:
def __init__(self):
self.name = ""
self.email = ""
self.courses = dict([])
self.report = []
self.dataFile = []
def __repr__(self):
return self.name + " " + self.email
class Department:
def __init__(self):
self.name = ""
self.instructors = dict([]) #contains Instructor objects
self.report = [] #subreport for the department
self.dataFile = []
def __repr__(self):
return self.name
class College:
def __init__(self):
self.name = ""
self.departments = dict([]) #contains Department objects
self.report = [] #subreport for the college
self.dataFile = []
def __repr__(self):
return self.name + ":" + `self.departments`
class University:
def __init__(self):
self.name = ""
self.colleges = dict([]) #contains College objects
def __repr__(self):
return self.name + ":" + `self.colleges`
#########################
### Utility Functions ###
#########################
def onReportPage(canv, doc):
#display general info at the top of every page
canv.setFont('Courier', 10)
canv.drawString(inch, 10.5*inch, "Wassamata U")
canv.drawString(inch, 10.35*inch, "Student Comments")
canv.drawString(5.75*inch, 10.5*inch, "Year/Term: " + uSemesterYear + "/" + uSemesterTerm)
canv.drawString(5.75*inch, 10.35*inch, " Semester: " + `semesterNumber`)
def xmlify(text):
return text.replace('&','&').replace('<','<').replace('>','>')
def semesterDescription(semesterNumber):
# reference semester is Spring 1964, i.e. semester 0
semesterNumber = semesterNumber / 10
year = `1964 + (semesterNumber / 3)`
term = "Spring"
if semesterNumber % 3 == 1:
term = "Summer"
elif semesterNumber % 3 == 2:
term = "Fall"
return year, term
#########################
######### Main ##########
#########################
# set up some options
# should have a ui later
# ugly, but quick
# used to get them on the top of every page
global uSemesterYear
global uSemesterTerm
print "\n"
university = University()
university.name = "Wassamata U"
commentsFile = open("spireport2.csv", "rb").read()
commentRecords = commentsFile.split("ô\r\n")
commentsArray = []
for commentRecord in commentRecords:
commentsArray.append(commentRecord.split("æ"))
commentsArray.pop()
print "Reading in the SPI file"
#read in data from file
for row in commentsArray:
#print row
# college
currentCollege = university.colleges.get(row[0])
if currentCollege == None:
currentCollege = College()
currentCollege.name = row[0].replace("/", " ")
university.colleges[row[0]] = currentCollege
#department
currentDepartment = currentCollege.departments.get(row[1])
if currentDepartment == None:
currentDepartment = Department()
currentDepartment.name = row[1].replace("/", " ")
currentCollege.departments[row[1]] = currentDepartment
#instructor
currentInstructor = currentDepartment.instructors.get(row[2] + row[3])
if currentInstructor == None:
currentInstructor = Instructor()
currentInstructor.name = row[3].replace("/", " ")
currentInstructor.email = row[2].replace("/", " ")
currentDepartment.instructors[row[2] + row[3]] = currentInstructor
#course
currentCourse = currentInstructor.courses.get(row[5] + row[6] + row[7])
if currentCourse == None:
currentCourse = Course()
currentCourse.prefix = row[5][:3]
currentCourse.number = row[5][3:]
currentCourse.section = row[6]
currentCourse.instructor = row[3]
currentCourse.email = row[2]
currentCourse.name = row[4]
currentCourse.semester = row[7]
currentCourse.enrollment = int(row[8])
currentInstructor.courses[row[5] + row[6] + row[7]] = currentCourse
data = row[9:9+kNumberOfQuestions]
currentCollege.dataFile.append(data) #split the data file by college for later
currentInstructor.dataFile.append(data)
currentDepartment.dataFile.append(data)
currentCourse.dataFile.append(data)
semesterNumber = int(university.colleges.values()[0].departments.values()[0].instructors.values()[0].courses.values()[0].semester)
uSemesterYear, uSemesterTerm = semesterDescription(semesterNumber)
reportDocContent = []
print "Processing the SPI comments"
for eachCollege in university.colleges.values():
print "\tProcessing " + eachCollege.name
collegeReportStartingIndex = len(reportDocContent)
reportDocContent.append(Spacer(0, 100))
reportDocContent.append(Paragraph("Student comments for " + eachCollege.name, headerParagraphStyle))
reportDocContent.append(PageBreak())
for eachDepartment in eachCollege.departments.values():
print "\t\tProcessing " + eachDepartment.name
departmentReportStartingIndex = len(reportDocContent)
reportDocContent.append(Spacer(0, 100))
reportDocContent.append(Paragraph("Student comments for " + eachDepartment.name, headerParagraphStyle))
reportDocContent.append(PageBreak())
for eachInstructor in eachDepartment.instructors.values():
print "\t\t\tProcessing " + eachInstructor.name
instructorReportStartingIndex = len(reportDocContent)
reportDocContent.append(Spacer(0, 100))
reportDocContent.append(Paragraph("Student comments for " + eachInstructor.name + ", " + eachInstructor.email, headerParagraphStyle))
reportDocContent.append(PageBreak())
for eachCourse in eachInstructor.courses.values():
courseReportStartingIndex = len(reportDocContent)
reportDocContent.append(Paragraph("<para leftIndent=54><b>Instructor Name:</b> " + eachCourse.instructor + "</para>", instructorParagraphStyle))
reportDocContent.append(Spacer(0, 10))
headerTableContent1 = [[eachDepartment.name + "/" + eachCollege.name, eachCourse.prefix + eachCourse.number + eachCourse.section, eachCourse.name], ["Department/School", "Course-Section Number", "Course Name"]]
headerTableContent2 = [[eachCourse.enrollment if eachCourse.enrollment > 0 else "Unknown",
len(eachCourse.dataFile),
("%.2f" % (float(len(eachCourse.dataFile))/eachCourse.enrollment*100) if eachCourse.enrollment != 0 else "0.00")],
["Number of Students Enrolled", "Number Responding", "% of Response"]]
reportDocContent.append(Table(headerTableContent1, style=headerTableStyle))
reportDocContent.append(Spacer(0, 10))
reportDocContent.append(Table(headerTableContent2, style=headerTableStyle))
i = 0
for i in range(0, kNumberOfQuestions):
question = ""
if i == 0:
question = "The thing(s) I like the MOST about this course:"
elif i == 1:
question = "The thing(s) I like the LEAST about this course:"
elif i == 2:
question = "What is your reaction to the method of evaluating your mastery of the course (i.e., testing, grading, out of class assignments (term papers), instructor feedback, etc.):"
elif i == 3:
question = "Additional comments and suggestions for improvement:"
reportDocContent.append(Spacer(0, 10))
reportDocContent.append(Paragraph(question, style=questionParagraphStyle))
reportDocContent.append(Spacer(0, 5))
commentParagraph = ""
for comments in eachCourse.dataFile:
if comments[i] != "":
commentParagraph += unicode(comments[i], 'latin-1') + "<br/>"
reportDocContent.append(Paragraph(commentParagraph, style=commentParagraphStyle))
eachCourse.report = reportDocContent[courseReportStartingIndex:]
reportDocContent.append(PageBreak())
eachInstructor.report = reportDocContent[instructorReportStartingIndex:]
eachDepartment.report = reportDocContent[departmentReportStartingIndex:]
eachCollege.report = reportDocContent[collegeReportStartingIndex:]
# build directory structure to put reports in
for eachCollege in university.colleges.values():
if (not os.path.exists(eachCollege.name)):
os.mkdir(eachCollege.name)
for eachDepartment in eachCollege.departments.values():
if (not os.path.exists(os.path.join(eachCollege.name, eachDepartment.name))):
os.mkdir(os.path.join(eachCollege.name, eachDepartment.name))
for eachInstructor in eachDepartment.instructors.values():
if (not os.path.exists(os.path.join(eachCollege.name, eachDepartment.name, eachInstructor.name + " - " + eachInstructor.email))):
os.mkdir(os.path.join(eachCollege.name, eachDepartment.name, eachInstructor.name + " - " + eachInstructor.email))
print "Building Comments Report PDFs"
for eachCollege in university.colleges.values():
print "\tBuilding Comments Report for " + eachCollege.name
collegeReportDoc = SimpleDocTemplate(os.path.join(eachCollege.name, eachCollege.name + " SPI Comments Report.pdf"), pagesize=portrait(LETTER), allowSplitting=1)
collegeReportDoc.leftMargin = .25*inch
collegeReportDoc.rightMargin = .25*inch
collegeReportDoc.bottomMargin = .25*inch
collegeReportDoc.build(eachCollege.report, onFirstPage=onReportPage, onLaterPages=onReportPage)
for eachDepartment in eachCollege.departments.values():
print "\t\tBuilding Comments Report for " + eachDepartment.name
departmentReportDoc = SimpleDocTemplate(os.path.join(eachCollege.name, eachDepartment.name, eachDepartment.name + " SPI Comments Report.pdf"), pagesize=portrait(LETTER), allowSplitting=1)
departmentReportDoc.leftMargin = .25*inch
departmentReportDoc.rightMargin = .25*inch
departmentReportDoc.bottomMargin = .25*inch
# import pdb; pdb.set_trace()
departmentReportDoc.build(eachDepartment.report, onFirstPage=onReportPage, onLaterPages=onReportPage)
print "\t\t\tBuilding Comments Reports for individual instructors"
for eachInstructor in eachDepartment.instructors.values():
instructorReportDoc = SimpleDocTemplate(os.path.join(eachCollege.name, eachDepartment.name, eachInstructor.name + " - " + eachInstructor.email, eachInstructor.name + " SPI Comments Report.pdf"), pagesize=portrait(LETTER), allowSplitting=1)
instructorReportDoc.leftMargin = .25*inch
instructorReportDoc.rightMargin = .25*inch
instructorReportDoc.bottomMargin = .25*inch
instructorReportDoc.build(eachInstructor.report, onFirstPage=onReportPage, onLaterPages=onReportPage)
#we do this one last because it's the biggest; otherwise it'd be at the beginning of the pdf report generation process
print "\tBuilding SPI Report for University"
reportDoc = SimpleDocTemplate("SPI Comments Report.pdf", pagesize=portrait(LETTER), allowSplitting=1)
reportDoc.leftMargin = .25*inch
reportDoc.rightMargin = .25*inch
reportDoc.bottomMargin = .25*inch
reportDoc.build(reportDocContent, onFirstPage=onReportPage, onLaterPages=onReportPage)
SpirePort2.csv:
College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example .comeان مصطلحات مدرسيةمطبيعيةالعلنائي uctoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample @example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & معلومات Affæhethealth Public Mgmtæexample@example.comوان المصطلحات الطبيةالطبيعيةæhsc3537æ0m01æ1370æ 205æsample تعليقات مثل ô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205æsample commentsææi like itæô College of Health & Public AffæHealth Info Mgmtæexample@ مثال على arhamentorroublogylogyologyologsologyhsc3537æ0m01æ1370æ 205ææ95ææs 20ampleample Tructoræmedical LeashsologyOnohsc3537æ0m01æ1370æ 205ææ 205æsample تعليقات مثل Itæô كلية الصحة والجمهور Affæhealth Info دعونا نرى ما يحدث ما يحدث كلية الصحة والجمهور العدالة {ô كلية الصحة والعقود العامة {{ô Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205ææææô College of Health & Public AffæHealth Info Mgmtæexample@example.comæAn InstructoræMEDICAL TERMINOLOGYæHSC3537æ0M01æ1370æ 205ææææô College of Arts & HumanitiesæEnglishæspam@me.comæAn InstructoræHARLEM, HAITI, AND HAVANAæAML3615æ0001æ1370æ 35ææææô College of Arts & HumanitiesæEnglishæspam@me.comæAn InstructoræCONT AMERICAN المرأة S الخيال 3283æ0001æ1370æ 35æOUæ 35æOUæ كلية الفنون والعلوم الإنسانيةالولايات المتحدةالعلين CTORæMAMJOR AMERICAL 4300æO0001O1370æ370æOUæ 33æOUæ كلية الفنون والعلوم الإنسانيةالعاقبالعملية
المحلول
وجدت الحل الحلوتي. بناء على بعض تغييرات التعليمات البرمجية المحرز في RST2PDF, ، كنت قادرا على الحصول على التعليمات البرمجية الخاصة بي بشكل موثوق. الحل، على الرغم من القبيح، هو التفاف كل ما عندي Paragraphs
في قسم التعليمات البرمجية التي تخلق Paragraphs
للحصول على تعليقات الطلاب في الداخل KeepTogether
. وبعد على سبيل المثال، قمت بتغيير خط واحد ذي صلة إلى:
reportDocContent.append(KeepTogether(Paragraph(commentParagraph, style=commentParagraphStyle)))
والآن تعمل (على الأقل، لم أتمكن من كسرها بعد بعد محاولة الكثير من البيانات العينة).
نصائح أخرى
يبدو أن هذا سؤال قديم لكنني عانيت من هذا الخطأ نفسه مؤخرا جدا، وجاء هنا للعثور على بعض النصائح. كان الإصلاح الذي قمت به هو جعل حجم فاصل نصف الحجم القديم. لقد كان سباكر سابقا (1،0.2 * بوصة) وأغيره إلى فاصل (1،0.1 * بوصة). ثم لا توجد المزيد من هذه الأخطاء.
fyi رسالة الخطأ حصلت عليه كان
File "/opt/python2.7/lib/python2.7/site-packages/reportlab-2.5-py2.7-linux-x86_64.egg/reportlab/platypus/doctemplate.py", line 1117, in build
BaseDocTemplate.build(self,flowables, canvasmaker=canvasmaker)
File "/opt/python2.7/lib/python2.7/site-packages/reportlab-2.5-py2.7-linux-x86_64.egg/reportlab/platypus/doctemplate.py", line 880, in build
self.handle_flowable(flowables)
File "/opt/python2.7/lib/python2.7/site-packages/reportlab-2.5-py2.7-linux-x86_64.egg/reportlab/platypus/doctemplate.py", line 793, in handle_flowable
raise LayoutError(ident)
reportlab.platypus.doctemplate.LayoutError: Flowable <Spacer at 0xf01440 frame=normal>...(1 x 14.4) too large on page 10 in frame 'normal'(439.275590551 x 628.28976378) of template 'Later'