2015-01-15 1 views
3

나는 창문에 파이썬 3.4.2 및 PyPDF2 1.24 (또한 도움이 경우 reportlab 3.1.44을 사용) 사용하고 있습니다 3.4로, 그리고 내 코드를 포팅하는 중입니다. 이 코드는 링크가 포함 된 빈 pdf 페이지를 작성하고 (reportlab 사용) 기존 PDF 페이지와 함께 (PyPDF2를 사용하여) 병합합니다. 난 그 BytesIO으로 변경 될 필요가 StringIO 사용되는 캔버스를 저장하여 reportlab에 문제가 있었다, 그러나 나는이 오류로 실행되었는지 일 후 : 여기 포팅 : PyPDF2 mergePage은() 내가 최근에 파이썬 2.7에서 업그레이드 7.</p> <p>형식 오류

Traceback (most recent call last): 
File "C:\cms_software\pdf_replica\builder.py", line 401, in merge_pdf_files 
    input_page.mergePage(link_page) 
File "C:\Python34\lib\site-packages\PyPDF2\pdf.py", line 2013, in mergePage 
    self.mergePage(page2) 
File "C:\Python34\lib\site-packages\PyPDF2\pdf.py", line 2059, in mergePage 
    page2Content = PageObject._pushPopGS(page2Content, self.pdf) 
File "C:\Python34\lib\site-packages\PyPDF2\pdf.py", line 1973, in _pushPopGS 
    stream = ContentStream(contents, pdf) 
File "C:\Python34\lib\site-packages\PyPDF2\pdf.py", line 2446, in __init 
    stream = BytesIO(b_(stream.getData())) 
File "C:\Python34\lib\site-packages\PyPDF2\generic.py", line 826, in getData 
    decoded._data = filters.decodeStreamData(self) 
File "C:\Python34\lib\site-packages\PyPDF2\filters.py", line 326, in decodeStreamData 
    data = ASCII85Decode.decode(data) 
File "C:\Python34\lib\site-packages\PyPDF2\filters.py", line 264, in decode 
    data = [y for y in data if not (y in ' \n\r\t')] 
File "C:\Python34\lib\site-packages\PyPDF2\filters.py", line 264, in 
    data = [y for y in data if not (y in ' \n\r\t')] 
TypeError: 'in <string>' requires string as left operand, not int 

는 라인과 역 추적 언급 경우 위의 라인 : 여기
link_page = self.make_pdf_link_page(pdf, size, margin, scale_factor, debug_article_links) 
if link_page != None: 
input_page.mergePage(link_page) 

는 make_pdf_link_page 기능의 관련 부분은 다음과 같습니다

packet = io.BytesIO() 
can = canvas.Canvas(packet, pagesize=(size['width'], size['height'])) 
....# left out code here is just reportlab specifics for size and url stuff 
can.linkURL(url, r1, thickness=1, color=colors.green) 
can.rect(x1, y1, width, height, stroke=1, fill=0) 
# create a new PDF with Reportlab that has the url link embedded 
can.save() 
packet.seek(0) 
try: 
    new_pdf = PdfFileReader(packet) 
except Exception as e: 
    logger.exception('e') 
    return None 
return new_pdf.getPage(0) 

나는 그것이 BytesIO를 사용하여 문제의 있으리라 믿고있어,하지만 난 페이지를 만들 수 없습니다 StringIO로 reportlab을 사용하는 연령. 이것은 Python 2.7에서 완벽하게 작동하는 데 사용되는 중요한 기능이므로, 이에 대한 피드백을 보내 주시면 감사하겠습니다. 감사!

업데이트 : 또한 BytesIO를 사용하지 않고 임시 파일에 쓰기 만하고 변경하려고 시도했습니다. 불행히도 나는 같은 오류가있어.

import tempfile 
temp_dir = tempfile.gettempdir() 
temp_path = os.path.join(temp_dir, "tmp.pdf") 
can = canvas.Canvas(temp_path, pagesize=(size['width'], size['height'])) 
.... 
can.showPage() 
can.save() 
try: 
    new_pdf = PdfFileReader(temp_path) 
except Exception as e: 
    logger.exception('e') 
    return None 
return new_pdf.getPage(0) 

UPDATE : 다음은 임시 파일 버전 나는이 정보의 흥미로운 비트를 발견했다. can.rect 및 can.linkURL 호출을 병합 할 것이라고 주석 처리하는 것 같습니다. 따라서 페이지에 그림을 그려 기존 PDF와 병합하려고하면 오류가 발생합니다.

답변

1

PyPDF2 라이브러리 코드를 파고 들자면 내 대답을 찾을 수있었습니다. 파이썬 3 사용자에게는 오래된 라이브러리가 까다로울 수 있습니다. 그들이 파이썬 3을 지원한다고해도, 반드시 모든 것을 테스트하지는 않습니다. 이 경우 문제는 PyPDF2의 filters.py에있는 ASCII85Decode 클래스에서 발생했습니다. 파이썬 3의 경우이 클래스는 바이트를 반환해야합니다. 필자는 pdfminer3k에서이 같은 유형의 함수에 대한 코드를 빌 렸습니다.이 함수는 pdfminer의 python 3 포트입니다. 이 코드에 대해 ASCII85Decode() 클래스를 교환하면 작동합니다.

import struct 
class ASCII85Decode(object): 
    def decode(data, decodeParms=None): 
     if isinstance(data, str): 
      data = data.encode('ascii') 
     n = b = 0 
     out = bytearray() 
     for c in data: 
      if ord('!') <= c and c <= ord('u'): 
       n += 1 
       b = b*85+(c-33) 
       if n == 5: 
        out += struct.pack(b'>L',b) 
        n = b = 0 
      elif c == ord('z'): 
       assert n == 0 
       out += b'\0\0\0\0' 
      elif c == ord('~'): 
       if n: 
        for _ in range(5-n): 
         b = b*85+84 
        out += struct.pack(b'>L',b)[:n-1] 
       break 
     return bytes(out) 
관련 문제