I want to pipe data via stdin to a Python script for onwards processing. The command is:
tail -f /home/pi/ALL.TXT | python3 ./logcheck.py
And the Python code is:
import sys
while 1:
if (sys.stdin.isatty()):
for line in sys.stdin:
print(line)
I want the code to continuously watch stdin and then process each row when received. The tail command is working when run on its own but the python script never outputs anything.
Checking isatty() it appears to always return False?
Help!
A TTY is when you use your regular terminal - as in opening up a python in your shell, and typing
BASH>python
>>>from sys import stdin
>>>stdin.isatty() #True
In your case the standard input is coming from something which is not a tty. Just add a not in the if statement.
Related
This is the app.py file.
#!/usr/bin/python3
import sys
def run():
print(sys.argv)
filename = sys.argv[1]
print(filename)
return
if __name__ == '__main__':
run()
I want to run this code from the command line, so I tried the two following lines each.
python3 app.py input.txt
python3 app.py < input.txt
The first command showed the result I expected, which is ['app.py', 'input.txt']. However the second command just ended up showing ['app.py'].
It seems like the Python code does not recognize the special symbols. How can I make the script recognize them without changing the script itself? i.e. not modifying the command like this: python3 app.py '<' input.txt.
The < character is special and will actually stream the file specified to stdin. You cannot override this behavior as it comes from your shell not python itself. Here is an example of what is really happening, and how you can get the file contents.
import sys
file_contents = sys.stdin.read() # This will read the entire stdin stream into file_contents
This will also work for the | character
echo "Hello, World" | python app.py
I am writing a program which utilises lua script and python script.
I am calling python script from within lua as:
-- lua
pipe = io.popen("python3 main.py", "w")
Now, when the python executes code I want to do something like this:
# python
sys.stdout.write(str(timevar))
The problem is that the timevar is being sent to the Linux terminal and I cannot catch it in pipe inside lua script with:
-- lua
result = pipe:read("*a")
Hence, how to send data via pipe? I am reading from the pipe with:
#python
import fileinput
info = [ line[:-1] for line in fileinput.input() ]
which works well, but writing to output does not, so I am not sure if I made a mistake somewhere or does the python ask for something else to be done?
How do I have it so that you pass in a python command to the exec() command, waits for completion, and print out the output of everything that just happened?
Many of the code out there uses StringIO, something that is not included in Python 3.5.
You can't. Exec just executes in place and returns nothing. Your best bet would be to write the command into a script and execute it with subprocess if you really want to catch all the output.
Here's an example for you:
#!/usr/bin/env python3
from sys import argv, executable
from tempfile import NamedTemporaryFile
from subprocess import check_output
with NamedTemporaryFile(mode='w') as file:
file.write('\n'.join(argv[1:]))
file.write('\n')
file.flush()
output = check_output([executable, file.name])
print('output from command: {}'.format(output))
And running it:
$ ./catchandrun.py 'print("hello world!")'
output from command: b'hello world!\n'
$
This is a simple code that logs into a linux box, and execute a grep to a resource on the box. I just need to be able to view the output of the command I execute, but nothing is returned. Code doesn't report any error but the desired output is not written.
Below is the code:
import socket
import re
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('linux_box', port=22, username='abc', password='xyz')
stdin, stdout, stderr = ssh.exec_command('grep xyz *.set')
output2 = stdout.readlines()
type(output2)
This is the output I get:
C:\Python34\python.exe C:/Python34/Paramiko.py
Process finished with exit code 0
You never actually print anything to standard output.
Changing last line to print(output2) should print value correctly.
Your code was likely based on interactive Python shell experiments, where return value of last executed command is printed to standard output implicitly. In non-interactive mode such behavior does not occur. That's why you need to use print function explicitly.
I've been playing with using the subprocess module to run python scripts as sub-processes and have come accross a problem with reading output line by line.
The documentation I have read indicates that you should be able to use subprocess and call readline() on stdout, and this does indeed work if the script I am calling is a bash script. However when I run a python script readline() blocks until the whole script has completed.
I have written a couple of test scripts that repeat the problem. In the test scripts I attmept to run a python script (tst1.py) as a sub-process from within a python script (tst.py) and then read the output of tst1.py line by line.
tst.py starts tst1.py and tries to read the output line by line:
#!/usr/bin/env python
import sys, subprocess, multiprocessing, time
cmdStr = 'python ./tst1.py'
print(cmdStr)
cmdList = cmdStr.split()
subProc = subprocess.Popen(cmdList, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
while(1):
# this call blocks until tst1.py has completed, then reads all the output
# it then reads empty lines (seemingly for ever)
ln = subProc.stdout.readline()
if ln:
print(ln)
tst1.py simply loops printing out a message:
#!/usr/bin/env python
import time
if __name__ == "__main__":
x = 0
while(x<20):
print("%d: sleeping ..." % x)
# flushing stdout here fixes the problem
#sys.stdout.flush()
time.sleep(1)
x += 1
If tst1.py is written as a shell script tst1.sh:
#!/bin/bash
x=0
while [ $x -lt 20 ]
do
echo $x: sleeping ...
sleep 1
let x++
done
readline() works as expected.
After some playing about I discovered the situation can be resolved by flushing stdout in tst1.py, but I do not understand why this is required. I was wondering if anyone had an explanation for this behaviour ?
I am running redhat 4 linux:
Linux lb-cbga-05 2.6.9-89.ELsmp #1 SMP Mon Apr 20 10:33:05 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Because if the output is buffered somewhere the parent process won't see it until the child process exists at that point the output is flushed and all fd's are closed. As for why it works with bash without explicitly flushing the output, because when you type echo in a most shells it actually forks a process that executes echo (which prints something) and exists so the output is flushed too.