Search code examples
pythoninterprocessinter-process-communicat

How to interact with Running Python Script


While my main script is running

class Blah():
    update=0

    def testthings(function):
        return function(9)

main = Blah()
while True:
    main.update+=1

How can I run an independent script to have access to the 'main variable' (defined in my main script) while the main script is running?

Something like this would be useful

main = GetMain()
while True:
    main.testthings(lambda x: x)

Solution

  • Use rpyc. It's clean, intuitive, and very powerful.

    Basically, you write a service class which exposes whichever interface you'd like (e.g. it has a method which returns that global variable you need), create a server object associated with that service, and start it. Then, in a client, you connect using a client object, and call that function, which returns the variable from the server process.

    EDIT: code sample for running the rpyc server, and connecting an rpyc client

    rpyc_main.py

    # main definitions
    import time
    class Blah():
        update=0
        def testthings(self, function):
            return function(9)
    
    # rpyc servic definition
    import rpyc
    
    class MyService(rpyc.Service):
        def exposed_testthings(self, function = lambda x: x):
            return main.testthings(function = function)
        def exposed_get_main_update(self):
            return main.update
    
    # start the rpyc server
    from rpyc.utils.server import ThreadedServer
    from threading import Thread
    server = ThreadedServer(MyService, port = 12345)
    t = Thread(target = server.start)
    t.daemon = True
    t.start()
    
    # the main logic
    main = Blah()
    while True:
        main.update+=1
        time.sleep(1)
    

    rpyc_client.py

    # rpyc client
    import rpyc
    conn = rpyc.connect("localhost", 12345)
    c = conn.root
    
    # do stuff over rpyc
    import time
    print 'update =', c.get_main_update()
    time.sleep(2)
    print 'update =', c.get_main_update()
    print 'testing returned:', c.testthings(lambda x: x)  # calling a method of the remote service
    print 'update =', c.get_main_update()
    

    output

    update= 6
    update= 8
    testing returned: 9
    update= 8
    

    Notes:

    1. a lambda object (actually, a rpyc-reference to that object) is passed from the client to the server. when it is being called, it actually runs in the client process. This is super cool and far from trivial. It works because rpyc is symmetric
    2. for ultra-flexibility, use rpyc's classic mode