Python - Disable Multiple Py Script Instances And Pass Their Args To Main Instance
Solution 1:
It is possible but not trivial because the processes are unrelated. So you have to set :
- an exclusion mechanism (file lock should be portable across architectures) to allow a process to know if it is the first - beware of race condition when a server is about to exit when a new process arrives ...
- the first process opens a listener - a socket on an unused port should be portable
- you must define a protocol to allow you processes to communicate over the socket
- when a process discovers it is not the first, it contacts the first over the socket and passes its arguments
So it can work, but it is a lot of work ...
There could be solutions a little simpler if you can limit you to a specific architectur (only Windows or only Linux) and make use of specific libraries, but it will nether be a simple job.
Solution 2:
Yes, something like this is possible. I'm not sure if it's possible to reliably detect if one instance (process) of the application is already running, but one possible way to do this is to reserve a TCP port for the program. The first application that starts will listen on that port and act like the server. Since only process can listen at the same port at the same time, all following processes will fail to create a listen socket and could then act like a client.
You could use a multiprocessing.connection
to implement this. The following is a working example to demonstrate the concept:
import multiprocessing.connection
import sys
SERVER_HOST = 'localhost'
SERVER_PORT = 6000
g_total = 0
def process_numbers(numbers):
global g_total
for number in numbers:
g_total += number
print('Adding number %d. Total is now %d.' % (number, g_total))
def server_main(listener, numbers):
process_numbers(numbers)
print('Starting server.')
while True:
client = listener.accept()
numbers = list(client.recv())
client.close()
if not numbers:
break
process_numbers(numbers)
def client_main(numbers):
client = multiprocessing.connection.Client((SERVER_HOST, SERVER_PORT), 'AF_INET')
print('Starting client.')
client.send(numbers)
def main():
numbers = map(int, sys.argv[1:])
try:
listener = multiprocessing.connection.Listener((SERVER_HOST, SERVER_PORT), 'AF_INET')
except OSError:
client_main(numbers)
else:
server_main(listener, numbers)
if __name__ == '__main__':
main()
Assuming you have saved the above code as main.py
, calling py main.py 1 2 3
will print the following output:
Adding number 1. Total is now 1.
Adding number 2. Total is now 3.
Adding number 3. Total is now 6.
Starting server.
The application will keep running. Now open a second terminal and run py main.py 4 5 6
. The script will only print:
Starting client.
However, your first application (acting as the server) will now print:
Adding number 4. Total is now 10.
Adding number 5. Total is now 15.
Adding number 6. Total is now 21.
If you repeat the command it prints:
Adding number 4. Total is now 25.
Adding number 5. Total is now 30.
Adding number 6. Total is now 36.
and so on. You can quit the server by calling the client without arguments.
NOTE: This answer was written for and tested in Python 3.7, since Python 2.x is already dead. But the multiprocessing.connection
also exists in Python 2.7, so I think the code should probably work in Python 2.7 as well (possibly with minor modifications).
Post a Comment for "Python - Disable Multiple Py Script Instances And Pass Their Args To Main Instance"