2

I'm new to python and have been struggling with this for quite a while. Okay so I have a program that logs into a server and then constantly pings the server every 10 seconds to see if the status of the server has changed. In the same script I have a function which sends a message to the server.

a simple example of the send method:

def send(self, message):

   url = ("https://testserver.com/socket?message=%s") % (message)

   req = urllib2.Request(url, None, None)
   response = urllib2.urlopen(req).read()

   print response

would it be possible for me to call this method from another script while this one was running? as in using the same session. It seems as though when I run my script which calls this function it creates a new instance of it instead of using the current instance of that script causing it to throw my exception saying I am not connected to the server.

Sorry for the noob question. I have tried googling for a while but I cant seem to find the answer. I have read the following but these didn't solve the problem:

Python call function within class

Python code to get current function into a variable?

Hi @nFreeze thanks for the reply I have tried to use ZeroRPC but every time I run the script/example you gave (obviously edited) I run into this error:

Traceback (most recent call last):
    File "C:\Users\dwake\Desktop\Web Projects\test.py", line 1, in <module>
import zerorpc
    File "C:\Python27\lib\site-packages\zerorpc\__init__.py", line 27, in <module>
from .context import *
    File "C:\Python27\lib\site-packages\zerorpc\context.py", line 29, in <module>
import gevent_zmq as zmq
    File "C:\Python27\lib\site-packages\zerorpc\gevent_zmq.py", line 33, in <module>
import gevent.event
    File "C:\Python27\lib\site-packages\gevent\__init__.py", line 48, in <module>
from gevent.greenlet import Greenlet, joinall, killall
    File "C:\Python27\lib\site-packages\gevent\greenlet.py", line 6, in <module>
from gevent.hub import greenlet, getcurrent, get_hub, GreenletExit, Waiter
    File "C:\Python27\lib\site-packages\gevent\hub.py", line 30, in <module>
greenlet = __import__('greenlet').greenlet
ImportError: No module named greenlet

Even though I have installed gevent. I'm not sure how to fix this. Have been googling for a good hour now.

Community
  • 1
  • 1
DeanMWake
  • 893
  • 3
  • 19
  • 38
  • A simple way would be to have two threads operating at the same time in the same process, one pinging the server and the other doing whatever other logic you please. Multithreading means that both 'threads' of execution are given CPU time in a fair distribution and share the same memory and process space. Alternatively, you could have script A write to a file and script B check the file for updates, or some similar mechanism (sqlite database, pipe...) – Patashu May 27 '13 at 13:06
  • 3
    ...But what you should understand is that your mental model needs to be corrected. By default, a program (in this case a python program) that is running is not automatically some kind of intelligent agent that can automatically be talked to by other programs and respond to them with the appropriate values. Programs by default only know what's happening inside of them and what they decide themselves they want to interact with. – Patashu May 27 '13 at 13:11
  • Thanks I have actually been programming java for about a year. Have c# and perl knowledge. I know programs arn't instantly small HAL 9000nd's. Thanks for pointing that out though it was quite constructive. What I need to do is pass parameters to an already created instance of a method. I was going to try with dropped files but this becomes messy unless I code a clean up process (more code for nothing). – DeanMWake May 27 '13 at 14:03

2 Answers2

3

What you're looking for is called an RPC server. It allows external clients to execute exposed functions in your app. Luckily python has many RPC options. ZeroRPC is probably my favorite as it is easy to use and supports node.js. Here is an example of how to expose your send method using ZeroRPC:

In your app (server)

import zerorpc

class HelloRPC(object):
    def send(self, message):
        url = ("https://testserver.com/socket?message=%s") % (message)
        req = urllib2.Request(url, None, None)
        response = urllib2.urlopen(req).read()
        return response    
s = zerorpc.Server(HelloRPC())
s.bind("tcp://0.0.0.0:4242")
s.run()

In the other app (client)

import zerorpc

c = zerorpc.Client()
c.connect("tcp://127.0.0.1:4242")
print c.send("RPC TEST!")
Community
  • 1
  • 1
mr.freeze
  • 13,731
  • 5
  • 36
  • 42
  • 1
    @MethodMan - what OS are you running? – mr.freeze May 27 '13 at 19:39
  • Hi, Running windows. I finally managed to fix it with a pre-compiled version but now im experiencing an "LostRemote: Lost remote after 10s heartbeat" exception. Not sure if I put the call in the wrong place. Im testing now :) Thanks for your help. Ill let you know if I get it working. – DeanMWake May 27 '13 at 20:22
  • Hmm should I be able to ping it or get a sort of wsdl when I go to the address? – DeanMWake May 27 '13 at 20:27
  • 1
    It uses tcp so make sure your firewall isn't blocking. Set a break point at def send and see if it is hitting the method. You can use a [command line client](https://github.com/dotcloud/zerorpc-python) on the same box to test. – mr.freeze May 27 '13 at 20:31
  • I've checked my firewall I used one of their examples and it seemed to work perfectly, The command line isnt working because I haven't set up my global variable for zerorpc. Not sure if there is any point? By set a breakpoint do you mean stop the client completely when it hits that method? or return a value? – DeanMWake May 27 '13 at 21:00
  • 1
    If their examples work then your send method is probably throwing an error. Wrap in a try except and return a message to confirm – mr.freeze May 27 '13 at 21:13
  • I have added their: def hello(self, name): return "Hello, %s" % name to my WAClient() class and I cant even seem to call that as they have explained. I still get the time out. Im not sure maybe it is thread locked? Perhaps I need to create the zerorpc in a new thread? – DeanMWake May 27 '13 at 21:18
1

Simpliest way is to use UNIX signals. You'll need no third-party libraries.

# your-daemon.py
import signal
from time import sleep

def main():
    while True:
        print "Do some job..."
        sleep(5)

def send():
    print "Send your data"

def onusr1(*args):
    send()

if __name__ == '__main__':
    signal.signal(signal.SIGUSR1, onusr1)
    main()

Run in terminal:

$ pgrep -f your-daemon.py | xargs kill -SIGUSR1

Of course, this works only in local machine. Also you can't specify any argument to send function, and if you want to have many handlers, then use RPC as adviced below.

Vladimir Lagunov
  • 1,895
  • 15
  • 15