views:

138

answers:

2

Hi,

I have not a lot of knowledge of python and network programming. Currently I am trying to implement a simple application which can receive a text message sent by the user, fetch some information from the google search api, and return the results via text message to the user. This application will continue to listening to the users messages and reply immediately.

How I get the text short message sent by the user? It's a program named fetion from the mobile supplier in China. The client side fetion, just like a instant communication tool, can send/receive messages to/from other people who are using mobile to receive/send SMS.

I am using a open source python program that simulates the fetion program. So basically I can use this python program to communate with others who using cell phone via SMS.

My core program is based on java, so I need to take this python program into java environment. I am using jython, and now I am available to send messages to users by some lines of java codes.

But the real question is the process of receving from users via SMS. In python code, a new thread is created to continuously listen to the user. It should be OK in Python, but when I run the similar process in Jython, the following exception occurs:

Exception in thread Thread:Traceback (most recent call last):
File "D:\jython2.5.1\Lib\threading.py", line 178, in _Thread__bootstrap
   self.run()
File "<iostream>", line 1389, in run
File "<iostream>", line 1207, in receive
File "<iostream>", line 1207, in receive
File "<iostream>", line 150, in recv
File "D:\jython2.5.1\Lib\select.py", line 223, in native_select
  pobj.register(fd, POLLIN)
File "D:\jython2.5.1\Lib\select.py", line 104, in register
  raise _map_exception(jlx)
error: (20000, 'socket must be in non-blocking mode')

The line 150 in the python code is as follows:

def recv(self,timeout=False):
    if self.login_type == "HTTP":
        time.sleep(10)
        return self.get_offline_msg()
        pass
    else:
        if timeout:
            infd,outfd,errfd = select([self.__sock,],[],[],timeout)//<---line 150 here
        else:
            infd,outfd,errfd = select([self.__sock,],[],[])

        if len(infd) != 0:
            ret = self.__tcp_recv()

            num = len(ret)
            d_print(('num',),locals())
            if num == 0:
                return ret
            if num == 1:
                return ret[0]
            for r in ret:
                self.queue.put(r)
                d_print(('r',),locals())

            if not self.queue.empty():
                return self.queue.get()

        else:
            return "TimeOut"

Because of I am not very familiar with python, especially the socket part, and also new in Jython use, I really need your help or only advice or explanation.

Thank you very much!

+1  A: 

The error states that you have tried to call select on a socket that is set (by default) to block waiting for input. The portable way to make it non-blocking is to find where self.__sock is created and call socket.setblocking(0) on it.

You could call - in principle - setblocking in recv prior to the select call but it would be confusing to the reader. As these are direct calls to the low-level socket routines, this isn't strictly a Python question but one about the operation of the socket system call as appropriate for your platform.

msw
A: 

As stated on the jython select documentaion page, only sockets in non-blocking mode can be multiplexed on jython, in contrast to cpython, where sockets can be either blocking or non-blocking.

http://wiki.python.org/jython/SelectModule#Onlysocketsinnon-blockingmodecanbemultiplexed

This is a limitation of Java that jython can do nothing to change.

There is a special function in the jython select module for this exact situation, the cpython_compatible_select function.

You don't show the import of the select module in your code above, but based on what I see, you must be doing an import like this

from select import select

If you replace that import with this

from select import cpython_compatible_select as select

Then everything should work fine.

Lastly, please make sure to read the "Warnings" section on the select module documentation page.

Alan Kennedy