Python: get name of file piped to stdin - python

I have a python program that reads input from stdin (required), and processes lines from stdin:
for lines in stdin:
#do stuff to lines
filename = #need file name
#example print
print(filename)
However, in this for loop, I also need to get the name of the file that has been piped in to this python program like this:
cat document.txt | pythonFile.py #should print document.txt with the example print
Is there a way to do this?

No, this is not possible. As the receiving end of a pipe you have no knowledge where your data stream is coming from. The use of cat further obfuscates it, but even if you would write ./pythonFile.py < document.txt you would have no clue.
Many unix tools accept filenames as argument and - as a special code for 'stdin'. You could design your script the same way, so it can be called like
cat document.txt | pythonFile.py - (your script doesn't know the input origin)
./pythonFile.py document.txt (your script does know the file)

Related

Running .py file with and argument in .bat

The problem: I want to iterate over folder in search of certain file type, then execute it with a program and the name.ext as argument, and then run python script that changes the output name of the first program.
I know there is probably a better way to do the above, but the way I thought of was this:
[BAT]
for /R "C:\..\folder" %%a IN (*.extension) do ( SET name=%%a "C:\...\first_program.exe" "%%a" "C:\...\script.py" "%name%" )
[PY]
import io
import sys
def rename(i):
name = i
with open('my_file.txt', 'r') as file:
data = file.readlines()
data[40] ='"C:\\\\Users\\\\UserName\\\\Desktop\\\\folder\\\\folder\\\\' + name + '"\n'
with open('my_file.txt', 'w') as file:
file.writelines( data )
if __name__ == "__main__":
rename(sys.argv[1])
Expected result: I wish the python file changed the name, but after putting it once into the console it seems to stay with the script. The BAT does not change it and it bothers me.
PS. If there is a better way, I'll be glad to get to know it.
This is the linux bash version, I am sure you can change the loop etc to make it work as batch file instead of your *.exe I use cat as a generic input output example
#! /bin/sh
for f in *.txt
do
suffix=".txt"
name=${f%$suffix}
cat $f > tmp.dat
awk -v myName=$f '{if(NR==5) print $0 myName; else print $0 }' tmp.dat > $name.dat
done
This produces "unique" output *.dat files named after the input *.txt files. The files are treated by cat (virtually your *.exe) and the output is put into a temorary file. Eventually, this is handled by awk changing line 5 here. with the output placed in the unique file, as mentioned above.

timing and redirecting subprocess:PIPE output to file

I'm trying to execute a bash and want to redirect the output on the shell to a file
this is what I have so far
baby = subprocess.Popen('some command', stdout = subprocess.PIPE, shell = True)
print (baby.stdout.readlines()) #i wanna see it in console
with open("log.txt","a") as fobj: #wanna create a file log.txt and save the output there as string
fobj.write(stdout)
but I get this error NameError: name 'stdout' is not defined
I've looked at these question Run subprocess and print output to logging , subprocess.Popen() doesn't redirect output to file , Can you make a python subprocess output stdout and stderr as usual, but also capture the output as a string? but to no avail, they were all too complex for me, i got lost in all the code..
can't i just redirect the stdout to a normal txt file?
and is there a way I can built a function to time the execution of that script and put it in that same log.txt file (i use time ./myscript.py to take the time but i also don't know how to redirect it to the txt file)
You should adjust this example however suits you
First create input.txt file
Then
import sys
with open(sys.argv[1], 'r') as input, open(sys.argv[2], 'w') as output:
for line in input:
output.write(str(line.strip()) + '\n')
You run it from command line(s4.py,you can rename it)
python s4.py input.txt output.txt
Output
obama
is
my boss
You can guess but output is same as input.

Import multiple files output from bash script into Python lists

I have a bash script that connects to multiple compute nodes and pulls data from each one depending on some arguments entered after the bash script is called. For simplicity sake, I'm essentially doing this:
for h in node{0..7}; do ssh $h 'fold -w 80 /program.headers | grep "RA"
| head -600 | tr -d "RA =" > '$h'filename'; done
I'm trying to take the 8 files that come out of this (each have 600 pieces of information) and save them each as a list in Python. I then need to manipulate them in Python (split and convert to float) to be able to plot the data with Matplotlib.
For a bash script that only outputs one file, I can easily make a variable name equal to check_output and then manipulate from there:
test = subprocess.check_output("./bashscript")
test_list = test.split()
test = [float(a) for a in test_list]
I am also able to read a saved file from my bash script by using:
test = subprocess.check_output(['cat', '/path/filename'])
test_list = test.split()
test = [float(a) for a in test_list]
The problem is, I'm working with over 80 files after I get all that I need. Is there some way in Python to say, "for every file made store the contents of that as a list"?
Instead of capturing data by using subprocess you can use os.popen() to execute scripts. The benefit of using it is that you can read the output of a command/script as you are reading a file. So you can use read(), readlines(),readline() according to your wish which all will give you a list. By using that you can execute the script and capture output like this
import os
output=os.popen("./bashscript").readlines() #now output has the op of bashsceipt with each line as a seperate item as list.
check this for more info on how to use os.popen(). check this to know difference between read(),readlines(),readline(),xreadlines()
Define a simple interface between your bash script and your python script
It looks like the simple interface used to be a print out of the file, but this solution did not scale to multiple files. Now, I recommend the interface be printing out the names of files created. It would look something like this:
filenames = subprocess.check_output("./bashscript").split()
for filename in filenames:
with open(filename) as file_obj:
file_data = [float(a) for a in file_obj.readlines()]
It looks like you are unfamiliar with Python but are familiar with bash. As a result, you are programming hobbled on bash crutches, instead you should embrace Python and use it in your application. You probably do not need the bash script at all.

Why doesn't "./myprog | file" work like "cat file | ./myprog"?

Hello I am new to Python and would like to know different execution modes of the python program, say for below my program runs fine in first mode but second mode gives me error.
cat inputfile | ./pythonprogram.py - works
./pythonprogram.py | inputfile -- doesn't work
Also what are the all the best practices in executing the program through parsing input files.
FYI.. i am on the google python babyname exercise and below is my program:-
PS: I haven't coded a decent complete code, but this is more like a draft before attempting to execute full program.
Did you perhaps mean:
./pythonprogram.py < inputfile
This takes the contents of inputfile and pipes it to your program.
On the other hand:
./pythonprogram.py | inputfile
Will take the output from your python program, try to execute inputfile (it can't), and then give it the output from the python program.

Using textfile as stdin in python under windows 7

I'm a win7-user.
I accidentally read about redirections (like command1 < infile > outfile) in *nix systems, and then I discovered that something similar can be done in Windows (link). And python is also can do something like this with pipes(?) or stdin/stdout(?).
I do not understand how this happens in Windows, so I have a question.
I use some kind of proprietary windows-program (.exe). This program is able to append data to a file.
For simplicity, let's assume that it is the equivalent of something like
while True:
f = open('textfile.txt','a')
f.write(repr(ctime()) + '\n')
f.close()
sleep(100)
The question:
Can I use this file (textfile.txt) as stdin?
I mean that the script (while it runs) should always (not once) handle all new data, ie
In the "never-ending cycle":
The program (.exe) writes something.
Python script captures the data and processes.
Could you please write how to do this in python, or maybe in win cmd/.bat or somehow else.
This is insanely cool thing. I want to learn how to do it! :D
If I am reading your question correctly then you want to pipe output from one command to another.
This is normally done as such:
cmd1 | cmd2
However, you say that your program only writes to files. I would double check the documentation to see if their isn't a way to get the command to write to stdout instead of a file.
If this is not possible then you can create what is known as a named pipe. It appears as a file on your filesystem, but is really just a buffer of data that can be written to and read from (the data is a stream and can only be read once). Meaning your program reading it will not finish until the program writing to the pipe stops writing and closes the "file". I don't have experience with named pipes on windows so you'll need to ask a new question for that. One down side of pipes is that they have a limited buffer size. So if there isn't a program reading data from the pipe then once the buffer is full the writing program won't be able to continue and just wait indefinitely until a program starts reading from the pipe.
An alternative is that on Unix there is a program called tail which can be set up to continuously monitor a file for changes and output any data as it is appended to the file (with a short delay.
tail --follow=textfile.txt --retry | mycmd
# wait for data to be appended to the file and output new data to mycmd
cmd1 >> textfile.txt # append output to file
One thing to note about this is that tail won't stop just because the first command has stopped writing to the file. tail will continue to listen to changes on that file forever or until mycmd stops listening to tail, or until tail is killed (or "sigint-ed").
This question has various answers on how to get a version of tail onto a windows machine.
import sys
sys.stdin = open('textfile.txt', 'r')
for line in sys.stdin:
process(line)
If the program writes to textfile.txt, you can't change that to redirect to stdin of your Python script unless you recompile the program to do so.
If you were to edit the program, you'd need to make it write to stdout, rather than a file on the filesystem. That way you can use the redirection operators to feed it into your Python script (in your case the | operator).
Assuming you can't do that, you could write a program that polls for changes on the text file, and consumes only the newly written data, by keeping track of how much it read the last time it was updated.
When you use < to direct the output of a file to a python script, that script receives that data on it's stdin stream.
Simply read from sys.stdin to get that data:
import sys
for line in sys.stdin:
# do something with line

Categories

Resources