2
  1. i have simple python echo server which uses sockets , and echoes random numbers to clients .
  2. i have another program which prints every 2 second values to stdout.

If it was just a script i could have redirected like this 'stdout' | python script.py , and fetch it in the script like this data = sys.stdin.read(). But it's a server , and it wont work like this.

Question: How to write such a python server, that it could listen/fetch values which come to stdout on Debian, and pass them further. I am not asking for a complete code. Just some ideas on getting stdout, considering the program is a server.

Continuosly coming values > stdout > server.py > send values further

3
  • is the other program that prints the values on the machine sending random numbers or is it on a machine listening to the numbers been sent? Commented Apr 30, 2011 at 21:22
  • Right now server.py is sending random numbers , just for test. But i need server.py to continuosly fetch stdout values being sent every 2 seconds. I just made up the other program which for examples generates values and sends them to the server through stdout. Commented Apr 30, 2011 at 21:27
  • You can read from stdin with sys.stdin.read() or like you would any other file handle .readlines() etc Commented Apr 30, 2011 at 21:29

1 Answer 1

4

I think you need something similar to Python subprocess. In that example, consider dmesg as your number generator, and the grep as your socket server; however, you will just open a PIPE in the socket server instead of spawning a shell command.

Assume you have two processes, the talker and server (in Python 2.x)...

talker.py

""" Call as talker.py <INTEGER_DELAY> """ import time import sys assert sys.version_info < (3, 0, 0) DELAY = int(sys.argv[1]) ii = 1 while True: sys.stdout.write("Talk every %i seconds, blabbed %i times\n" % (DELAY, ii)) sys.stdout.flush() ii += 1 time.sleep(DELAY) 

server.py

#!/usr/bin/env python from subprocess import Popen, PIPE from os import kill import signal import sys assert sys.version_info < (3, 0, 0) talkpipe = Popen(['python', 'talker.py', '3'], shell=False, stdout=PIPE) try: while True: line = talkpipe.stdout.readline() print "SERVER HEARD", line.strip() except KeyboardInterrupt: print "Killing child..." kill(talkpipe.pid, signal.SIGTERM) 

Running this with ./server.py yields...

[mpenning@Bucksnort tmp]$ python server.py SERVER HEARD Talk every 3 seconds, blabbed 1 times SERVER HEARD Talk every 3 seconds, blabbed 2 times SERVER HEARD Talk every 3 seconds, blabbed 3 times SERVER HEARD Talk every 3 seconds, blabbed 4 times ^CTraceback (most recent call last): File "talker.py", line 11, in <module> time.sleep(DELAY) KeyboardInterrupt Killing child... [mpenning@Bucksnort tmp]$ 

The (more robust) Python3 versions of these scripts are...

talker.py

 """ talker.py: run talker.py with continuous stdout stream and control-C handling. talker.py was written for Python3, but it should be fine under Python 2.X... - To run under python 2.x, set `ENFORCE_PYTHON_3 = 0` Execute with: 'python talker.py <DELAY_INTEGER>' """ import signal import types import time import sys import os CATCH_CONTROL_C = 1 ENFORCE_PYTHON_3 = 1 BOUNDARY_CONDITIONS_SET = 0 def custom_signal_handler(signum, stackframe): assert isinstance(signum, int) assert isinstance(stackframe, types.FrameType) assert isinstance(BOUNDARY_CONDITIONS_SET, int) and BOUNDARY_CONDITIONS_SET >= 1 print("---> custom_signal_handler() got signal: %s <---" % signum) if signum == 0: # signal.SIG_DFL print(repr(stackframe)) elif signum == 2: # signal.SIGINT assert CATCH_CONTROL_C >= 1 raise KeyboardInterrupt(repr(stackframe)) else: raise NotImplementedError("Cannot handle signal %s" % signal.signum) def set_boundary_conditions(): global BOUNDARY_CONDITIONS_SET global DELAY_INTEGER assert isinstance(BOUNDARY_CONDITIONS_SET, int) assert BOUNDARY_CONDITIONS_SET <= 0 if ENFORCE_PYTHON_3 == 1: assert tuple(sys.version_info) >= (3, 0, 0) # len(sys.argv) will be 1 if this script is imported into python # len(sys.argv) will be >= 2 if this script was called from CLI w/ args if len(sys.argv) == 1: # Called from an import statement... assert sys.argv[0] == '' DELAY_INTEGER = 1 elif len(sys.argv) >= 2: # Called from the command-line... sys.argv[0] is the file name... assert sys.argv[0] == os.path.basename(__file__).strip() print("FOO", sys.argv[0]) DELAY_INTEGER = int(sys.argv[1]) assert DELAY_INTEGER > 0 else: raise ValueError("DELAY_INTEGER was not specified correctly in the CLI") if CATCH_CONTROL_C >= 1: assert custom_signal_handler # Send control-C to the custom signal handler... signal.signal(signal.SIGINT, custom_signal_handler) print(" The current handler for signal.SIGINT is %s" % custom_signal_handler) else: assert signal.SIG_DFL # signal.SIGINT (control-C) is 2... signal.signal(signal.SIGINT, signal.SIG_DFL) print("The current handler for signal.SIGINT is signal.SIG_DFL") BOUNDARY_CONDITIONS_SET = 1 def loop_talking_over_stdout(): """ Write messages to stdout with a variable delay... This function (loop_talking_over_stdout()) is a blocking call... """ assert BOUNDARY_CONDITIONS_SET >= 1 ii = 1 while True: sys.stdout.write("Talk every %i seconds, blabbed %i times\n" % ( DELAY_INTEGER, ii)) sys.stdout.flush() ii += 1 time.sleep(DELAY_INTEGER) if __name__=="__main__": print("running python %s" % list(sys.version_info)) set_boundary_conditions() loop_talking_over_stdout() 

server.py

#!/usr/bin/env python3 from subprocess import Popen, PIPE from os import kill import signal import shlex import sys import os assert sys.version_info >= (3, 0, 0,) def custom_signal_handler(signum, stackframe): assert isinstance(signum, int) print("Got signal: %s" % signum) raise KeyboardInterrupt(repr(stackframe)) # Send control-C to the custom signal handler... signal.signal(signal.SIGINT, custom_signal_handler) TIMEOUT = 3 while True: filepath = os.sep.join((os.getcwd(), 'talker.py')) cmd = 'python3 %s %s' % (filepath, TIMEOUT) talkpipe = Popen(shlex.split(cmd), shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout = talkpipe.stdout stderr = talkpipe.stderr stdin = talkpipe.stdin for line_out in iter(stdout.readline, b''): print(b'out>>> ' + line_out.rstrip()) for line_err in iter(stderr.readline, b''): print(b'err-->' + line_err) 
Sign up to request clarification or add additional context in comments.

7 Comments

I have a question . I did the way u suggested. I will show the code above and i got the error , i guess because my server was already running when i tried to pass values through pipe , and it gave error that i didn't specify args or something like that . So the question is : everytime i pass value through pipe it executes the file to what it passed the value or not ?
@Viktor, the description is inadequate to help without knowing the error, the way you called the number generation program with subprocess, and the way you attached stdout of that program to stdin in your socket server.
@Mike Maybe i just messed something with format , because it sends also stderr and stdout whtich are None,None , but as i see it is not pleased with my args[0] , which i have to specify when i run server , why i conclude that it kind of runs server.py and doesn't just pass stdin. File "myslowpoetry.py", line 36, in parse_args poetry_file = args[0] IndexError: list index out of range (None, None)
@Mike Yep . I just checked , the error is exactly because it doesn't pass args[0] , which means that everytime i execute send_random_number.py through pipe , it executes the other file to which pipe is linked , which is completely wrong for my server because it needs to be run ones , and just passed values through PIPE. Shit ....=)
@Viktor, you misunderstood what I was pointing to with the docs... I posted code that illustrates
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.