【问题标题】:How to debug crashing openoffice with pyuno如何使用 pyuno 调试崩溃的 openoffice
【发布时间】:2013-12-31 11:38:04
【问题描述】:

我想使用 openoffice 以编程方式将 docx 转换为 pdf。我知道 unoconv 可以做到这一点,而且 unoconv 确实会为我做到这一点,即使我运行一个单独的侦听器(使用unoconv -l)并调用unoconv -n(这样如果它无法连接到侦听器就会死掉) .因此,我假设我的 openoffice/pyuno 环境是健全的。

但是,当我运行 unoconv 侦听器(或手动调用 openoffice 作为接受器)并尝试使用我自己的 python 代码(从 unoconv 派生,并与另一个 openoffice 库进行交叉检查)连接时,侦听器死了,并且uno 桥死了。

我从监听器得到的错误是:

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

我在python端得到的错误是:

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

【问题讨论】:

  • 我应该补充一点,我遇到麻烦的最直接原因是我正在向 uno 传递一个由 io.TextIOWrapper 支持的流,即 unicode 流而不是字节流。
  • 这个异常最初是在哪一行引发的?
  • @TankorSmash 没有堆栈跟踪,这就是为什么这很令人费解。
  • 你的意思是在它被except RuntimeException as e 类型的行之一捕获之前没有任何痕迹?使用tb 模块构建堆栈跟踪怎么样?
  • @TankorSmash 不,我是认真的。

标签: python python-2.7 openoffice.org uno pyuno


【解决方案1】:

我不知道这是否是你的情况,但我发现 LogMeIn(在我的机器上运行)也在使用端口 2002。当我在那台机器上尝试 unoconv 时,我得到了同样的错误:Binary URP bridge通话期间处置。 我杀死了 LogMeIn,之后一切正常。

希望这会有所帮助!

【讨论】:

  • 我的问题的直接原因如上面的评论所述;但是很明显,pyuno 桥有许多脆弱性。
猜你喜欢
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多