2013-12-12 33 views
3

我想使用openoffice以編程方式將docx轉換爲pdf。我知道unoconv可以做到這一點,而且即使我運行一個單獨的偵聽器(使用unoconv -l)並調用unoconv -n(以便在它無法連接到偵聽器時它會死掉),unoconv也會爲我執行此操作。因此,我認爲我的openoffice/pyuno環境是理智的。但是,當我運行unoconv偵聽器(或手動調用openoffice作爲acceptor),並嘗試連接我自己的python代碼(從unoconv派生,並與另一個openoffice庫交叉檢查)時,偵聽器死亡,並且uno橋死亡。如何使用pyuno調試崩潰的openoffice

我從聽衆得到的錯誤是:

terminate called after throwing an instance of 'com::sun::star::uno::RuntimeException' 

我得到蟒結束的錯誤是:

unoconv: RuntimeException during import phase: 
Office probably died. Binary URP bridge disposed during call 

我真的不知道如何去這裏診斷問題。任何關於潛在原因或如何診斷的建議都將不勝感激。下面

代碼:

#dependency on openoffice-python 
import openoffice.streams as oostreams 
import openoffice.officehelper as oohelper 
import uno, unohelper 
from com.sun.star.beans import PropertyValue 
from com.sun.star.connection import NoConnectException 
from com.sun.star.document.UpdateDocMode import QUIET_UPDATE 
from com.sun.star.lang import DisposedException, IllegalArgumentException 
from com.sun.star.io import IOException, XOutputStream 
from com.sun.star.script import CannotConvertException 
from com.sun.star.uno import Exception as UnoException 
from com.sun.star.uno import RuntimeException 

import logging 
logger = logging.getLogger(__name__) 


#connectionstring = 'uno:socket,host=127.0.0.1,port=2002;urp;StarOffice.ComponentContext' 
connectionstring = 'socket,host=127.0.0.1,port=2002' 
## context = uno.getComponentContext() 
## svcmgr = context.ServiceManager 
## resolver = svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", context) 

## unocontext = resolver.resolve("uno:%s" % connectionstring) 
unocontext = oohelper.connect(connectionstring) 

#unosvcmgr = unocontext.ServiceManager 
desktop = unocontext.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext) 


class OutputStream(unohelper.Base, XOutputStream): 
    def __init__(self, stream=None): 
     self.closed = 0 
     self.stream = stream if stream is not None else sys.stdout 

    def closeOutput(self): 
     self.closed = 1 

    def writeBytes(self, seq): 
     self.stream.write(seq.value) 

    def flush(self): 
     pass 

def UnoProps(**args): 
    props = [] 
    for key in args: 
     prop = PropertyValue() 
     prop.Name = key 
     prop.Value = args[key] 
     props.append(prop) 
    return tuple(props) 



FILTERS = {'pdf': 'writer_pdf_Export'} 

def convert_stream(instream, outstream, 
        outdoctype=None, outformat=None): 
    '''instream and outstream are streams. 
    outdoctype and outformat are strings. They correspond 
    to the first two parameters to the Fmt constructor.To 
    convert to pdf use outdoctype="document", 
    outformat="pdf". 
    If you choose inappropriate values, an ValueError 
    will result.''' 
    #fmts is a global object of type FmtList 

    outputfilter = FILTERS[outformat] 

    inputprops = UnoProps(Hidden=True, ReadOnly=True, UpdateDocMode=QUIET_UPDATE, InputStream=oostreams.InputStream(instream)) 
    inputurl = 'private:stream' 
    convert_worker(inputurl,inputprops,outputfilter,outstream=outstream) 
    return outstream 


def convert_worker(inputurl, inputprops, outputfilter, outstream=None,inputfn=None): 
    global exitcode 

    document = None 

    try: 
     ### Import phase 
     phase = "import" 

     document = desktop.loadComponentFromURL(inputurl , "_blank", 0, inputprops) 

     if not document: 
      raise UnoException("The document '%s' could not be opened." % inputurl, None) 

     ### Import style template 
     phase = "import-style" 

     ### Update document links 
     phase = "update-links" 
     try: 
      document.updateLinks() 
     except AttributeError: 
      # the document doesn't implement the XLinkUpdate interface 
      pass 

     ### Update document indexes 
     phase = "update-indexes" 
     for ii in range(2): 
      # At first update Table-of-Contents. 
      # ToC grows, so page numbers grows too. 
      # On second turn update page numbers in ToC. 
      try: 
       document.refresh() 
       indexes = document.getDocumentIndexes() 
      except AttributeError: 
       # the document doesn't implement the XRefreshable and/or 
       # XDocumentIndexesSupplier interfaces 
       break 
      else: 
       for i in range(0, indexes.getCount()): 
        indexes.getByIndex(i).update() 

     ### Export phase 
     phase = "export" 

     outputprops = UnoProps(FilterName=outputfilter, OutputStream=OutputStream(stream=outstream), Overwrite=True) 
     outputurl = "private:stream" 

     try: 
      document.storeToURL(outputurl, tuple(outputprops)) 
     except IOException as e: 
      raise UnoException("Unable to store document to %s (ErrCode %d)\n\nProperties: %s" % (outputurl, e.ErrCode, outputprops), None) 

     phase = "dispose" 
     document.dispose() 
     document.close(True) 

    except SystemError as e: 
     logger.error("unoconv: SystemError during %s phase:\n%s" % (phase, e)) 
     exitcode = 1 

    except RuntimeException as e: 
     logger.error("unoconv: RuntimeException during %s phase:\nOffice probably died. %s" % (phase, e)) 
     exitcode = 6 

    except DisposedException as e: 
     logger.error("unoconv: DisposedException during %s phase:\nOffice probably died. %s" % (phase, e)) 
     exitcode = 7 

    except IllegalArgumentException as e: 
     logger.error("UNO IllegalArgument during %s phase:\nSource file cannot be read. %s" % (phase, e)) 
     exitcode = 8 

    except IOException as e: 
     #   for attr in dir(e): print '%s: %s', (attr, getattr(e, attr)) 
     logger.error("unoconv: IOException during %s phase:\n%s" % (phase, e.Message)) 
     exitcode = 3 

    except CannotConvertException as e: 
     #   for attr in dir(e): print '%s: %s', (attr, getattr(e, attr)) 
     logger.error("unoconv: CannotConvertException during %s phase:\n%s" % (phase, e.Message)) 
     exitcode = 4 

    except UnoException as e: 
     if hasattr(e, 'ErrCode'): 
      logger.error("unoconv: UnoException during %s phase in %s (ErrCode %d)" % (phase, repr(e.__class__), e.ErrCode)) 
      exitcode = e.ErrCode 
      pass 
     if hasattr(e, 'Message'): 
      logger.error("unoconv: UnoException during %s phase:\n%s" % (phase, e.Message)) 
      exitcode = 5 
     else: 
      logger.error("unoconv: UnoException during %s phase in %s" % (phase, repr(e.__class__))) 
      exitcode = 2 
      pass 
+0

我應該補充一點,我的麻煩最接近的原因是我傳遞給uno一個由'io.TextIOWrapper'支持的流,即unicode流而不是bytestream。 – Marcin

+0

最初提出的例外是什麼? – TankorSmash

+0

@TankorSmash沒有堆棧跟蹤,這就是爲什麼這是如此令人費解。 – Marcin

回答

1

我不知道這可能是你的情況,但我發現,LogMeIn的(在我的機器上運行)也使用的端口2002。當我嘗試對unoconv機器,我得到同樣的錯誤:在通話期間佈置的二進制URP橋。 我殺了LogMeIn,之後一切正常。

希望這會有所幫助!

+0

我的問題的最根本原因如上面的評論中所述;然而很明顯pyuno橋有很多脆弱性。 – Marcin