Search code examples
pythonexcelweb-servicesspyne

How to return XLS file with spyne?


I am trying to return XLS file throught webservice created with spyne.

Here is mine code, now, I don't know what to do..

@spyne.srpc(Unicode, _returns=Iterable(Unicode))    
def Function(A):
     GetXLS(A)     
     kalist = open("file.xls", 'r');
     return kalist

The most important lines are last 2. :)

I am thinking about this: Is it possible to return xls file with spyne or should I do something with that xls and then return that?

Thank you for all your answers

PS: That xls is from BLOB file (from Oracle DB), so, if needed, I have BLOB too..

Edit:

This is that AssertionError that appeared:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [14/Jul/2016 07:15:19] "GET /soap/oracleservice?wsdl HTTP/1.1" 200 -
ERROR:spyne.util:
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\spyne\util\__init__.py", line 120, in start
    next(ret)
  File "C:\Python27\lib\site-packages\spyne\protocol\xml.py", line 782, in _get_members_etree
    sub_name)
  File "C:\Python27\lib\site-packages\spyne\protocol\xml.py", line 463, in to_parent
    return handler(ctx, cls, inst, parent, ns, *args, **kwargs)
  File "C:\Python27\lib\site-packages\spyne\protocol\xml.py", line 616, in modelbase_to_parent
    elt.text = self.to_unicode(cls, inst)
  File "C:\Python27\lib\site-packages\spyne\protocol\_outbase.py", line 211, in to_unicode
    return handler(class_, value, *args, **kwargs)
  File "C:\Python27\lib\site-packages\spyne\protocol\_outbase.py", line 441, in file_to_unicode
    return self.file_to_string(cls, value, suggested_encoding)
  File "C:\Python27\lib\site-packages\spyne\protocol\_outbase.py", line 421, in file_to_string
    assert False
AssertionError
127.0.0.1 - - [14/Jul/2016 07:15:21] "POST /soap/oracleservice HTTP/1.1" 200 -
INFO:werkzeug:127.0.0.1 - - [14/Jul/2016 07:15:21] "POST /soap/oracleservice HTTP/1.1" 200 -

Solution

  • The best way to do this is to set the return type to File (docs) and return a File.Value object.

    For your case, that means:

    @spyne.rpc(Unicode, _returns=File)    
    def kalibracniList(ctx, MEC):
        from OracleDB import VraceniListu
        VraceniListu(MEC);
        sleep(1)
        return File.Value(path='FILE_NAME.xls');
    

    However, due to a bug in 2.12, you can't do this. You can do the following as a workaround:

    @spyne.rpc(Unicode, _returns=File)    
    def kalibracniList(ctx, MEC):
        from OracleDB import VraceniListu
        VraceniListu(MEC);
        sleep(1)
        return File.Value(handle=open('FILE_NAME.xls', 'rb'));
    

    Note that this will fail with "Internal Error" if the open() call throws for some reason. If you don't want this to happen, you must manually do your own exception handling around the open() call. You should also make sure to open the file in binary mode if you care about python3 compatibility at all.

    For 2.13 and later (which is not released yet), you won't need this workaround. If you feel adventurous, you can install 2.13.0-alpha via:

    pip install -e git://github.com/arskom/spyne.git@spyne-2.13.0-alpha#egg=spyne