I am running a script in python like this from the prompt:
python gp.py /home/cdn/test.in..........
Inside the script i need to take the path of the input file test.in and the script should read and print from the file content. This is the code which was working fine. But the file path is hard coded in script. Now I want to call the path as a command line argument.
Working Script
#!/usr/bin/python
import sys
inputfile='home/cdn/test.in'
f = open (inputfile,"r")
data = f.read()
print data
f.close()
Script Not Working
#!/usr/bin/python
import sys
print "\n".join(sys.argv[1:])
data = argv[1:].read()
print data
f.close()
What change do I need to make in this ?
While Brandon's answer is a useful solution, the reason your code is not working also deserves explanation.
In short, a list of strings is not a file object. In your first script, you open a file and operate on that object (which is a file object.). But writing ['foo','bar'].read() does not make any kind of sense -- lists aren't read()able, nor are strings -- 'foo'.read() is clearly nonsense. It would be similar to just writing inputfile.read() in your first script.
To make things explicit, here is an example of getting all of the content from all of the files specified on the commandline. This does not use fileinput, so you can see exactly what actually happens.
# iterate over the filenames passed on the commandline
for filename in sys.argv[1:]:
# open the file, assigning the file-object to the variable 'f'
with open(filename, 'r') as f:
# print the content of this file.
print f.read()
# Done.
Check out the fileinput module: it interprets command line arguments as filenames and hands you the resulting data in a single step!
http://docs.python.org/2/library/fileinput.html
For example:
import fileinput
for line in fileinput.input():
print line
In the script that isn't working for you, you are simply not opening the file before reading it. So change it to
#!/usr/bin/python
import sys
print "\n".join(sys.argv[1:])
f = open(argv[1:], "r")
data = f.read()
print data
f.close()
Also, f.close() this would error out because f has not been defined. The above changes take care of it though.
BTW, you should use at least 3 chars long variable names according to the coding standards.
Related
Apologies in advance if this has already been asked, but I have spent hours searching for answers on this. I'm a new student to Python (3.5.1, Windows 10) and my task is to write a function that reads the contents of a Fasta file (whose name is given by the user) and creates a new file (name also given by user, could be .fasta or .txt) with the Fasta sequences in uppercase. A fasta file is formatted so the title of a sequence is preceded by a caret and the subsequent lines are characters (those that I want to uppercase). A fasta file may have multiple >lines incorporated throughout the file, I do not want to uppercase these lines.
import sys
def fasta_upper(fasta_input_file, fasta_output_file):
fasta_input_file = sys.argv
with open('fasta_input_file', 'r') as f:
file_contents = f.read()
temp_contents = file_contents[:]
for line in temp_contents:
if line.startswith('>'):
pass
else:
g = line.upper()
open('fasta_output_file', 'w')
fasta_output_file.write(g)
fasta_input_file.close()
fasta_output_file.close()
For example this Fasta File:
Name of sequence
cgtatgggggtattccgtagctctgctgacgcgcttatatttagc
cgctcgatctggaggactctgcgatcgcggcatcgagctagcggc
Would be written like this:
Name of sequence
CGTATGGGGGGTATTCCGTAGCTCTGCTGACGCGCTTATATTTAGC
CGCTCGATCTGGAGGACTCTCGATCGCGGCATCGAGCTAGCGCGGC
I'm sure this is just riddled with obvious mistakes, but again I'm am a student trying to learn. Please be gentle! Thank you in advance for any advice or tips you have, I have really enjoyed Python and I'd like to overcome this frustration and become a more affluent programmer :)
A few corrections/improvements:
1) If you are opening the file with a "with" statement, you do not have to explicitly close it. With does this for you.
fasta_input_file.close() is therefore not neeeded.
2) For every line that does not begin with '>', this code is opening the 'fasta_output_file', overwriting the line and then closing it. Instead what you need to do is this.
initialise the variable outfile before the 'with' statement (So that you do not have to open and close inside the loop) outfile = open('fasta_output_file', 'a')
Write to the file in the else statement (outfile.write(g) should be in the else statement).
Close the output file after the 'with' statement exits. outfile.close()
A few more points:
You need to call the write() and close() methods on the file object that is created when you open the file.
Also, you are passing the filenames as the argument to the function and also trying to read from the command line arguments. You need to do only one of the two.
You overwrite the passed fasta_input_file immediately with sys.argv. It's unclear whether the names should come from the caller or from arguments.
sys.argv is the sequence of arguments. You probably want the second one, sys.argv[1].
You are confusing strings with names. 'fasta_input_file' is not the same as fasta_input_file.
When you read a file with read(), it becomes a string. Iterating a string produces single characters rather than entire lines.
Rather than checking a condition and then doing pass if it's met, check for not that condition and then do whatever needs to be done in there.
'fasta_output_file' is, again, not the same as fasta_output_file.
You opened the output file but didn't save a reference (e.g. out = open(...) or create a context manager (e.g. with open(...) as out:).
You are closing the input and output files after a single "line."
Here is a sample of what your code might look like with these errors taken care of:
import sys
def fasta_upper():
fasta_input_file, fasta_output_file = sys.argv[1], sys.argv[2]
with open(fasta_input_file) as f, open(fasta_output_file, 'w') as output:
for line in f:
if not line.startswith('>'):
line = line.upper()
output.write(line)
fasta_upper()
import sys
import re
if len(sys.argv) < 3:
print('Usage:\n\t{} <input file> <output file>'.format(sys.argv[0]))
sys.exit(1)
pattern = re.compile(r'\b[acgturykmswbdhvnx\-]+\b', re.M)
def repl(m):
return m.group(0).upper()
with open(sys.argv[1], 'r') as in_fh, open(sys.argv[2], 'w') as out_fh:
for line in in_fh:
if line.startswith('>'):
out_fh.write(line)
else:
out_fh.write(pattern.sub(repl, line))
I have multiple .txt files in a source folder of which i have given the path in "src" .I want to search strings which looks like "abcd.aiq" and print them in a file which i named as "fi".
I have written the following code and it doesnt print anything inside the file although it doesnt give any error.
import glob
import re
import os
src = (C:\Auto_TEST\Testing\Automation")
file_array= glob.glob(os.path.join(src,".txt"))
fi= open("aiq_hits.txt","w")
for input_file in file_array:
fo=open(input_file,"r")
line=fo.readline()
for line in fo:
line=r.strip()
x= re.findall('\S*.aiq\S*',line)
line= fo.readline()
for item in x:
fi.write("%s\n" %item)
fo.close()
fi.close()
I suppose this is what you are trying:
import glob
import re
import os.path
src = 'C:/Auto_TEST/Testing/Automation'
file_array = glob.glob(os.path.join(src,'*.txt'))
with open("aiq_hits.txt","w") as out_file:
for input_filename in file_array:
with open(input_filename) as in_file:
for line in in_file:
match = re.findall(r'\S*.aiq\S*', line)
for item in match:
out_file.write("%s\n" %item)
Let me quickly describe the changes I've made:
Opening files directly is not always a good idea. If the script crashes, the opened file object isn't being closed again, which can lead to data loss.
Since PEP 343 Python has the with statement, wich is generally agreed on being a better solution when handling files.
Calling f.readline() multiple times results in the script skipping these lines, because for line in f: reads lines on its own.
Finally, after every matching item you found you've been closing both the input file and the output file, so further reading or writing isn't possible anymore.
Edit: If you might need to tweak your regex, this might be a useful resource.
I am writing a script to log into a switch, write the config to a file, and then rename the file. I have the parts working separately. The issue is that I cannot figure out how to get all parts with in the same function so that I can use the function on a list of devices. I get a file not open for reading in the for 'line in f' statement. when as far as i can see the file is still open.
I have tried writing a function to rename the file that works on its own, but not when in this script with the other parts.
I have another script that i wrote that has the rename portion outside of the function which works, but will not work to rename the file if multiple hosts are called with the Exscript 'quickstart' module.
Thanks for any help,
from Exscript.util.start import quickstart
import os
import datetime
import time
time = datetime.datetime.now().strftime("%d-%m-%Y")
tm = 'c:/test/tmp.txt'
def do_something(job, host, conn):
f = open(tm, 'w+') #opens File with read and write permissions
conn.execute('term len 0')
conn.execute('sh run')
f.write(conn.response)
conn.execute('quit')
#this is the part where the error comes
for line in f:
if "hostname" in line:
host = line.strip()
test = 'c:/test/' + host[9:] + 'on' + time + '.txt'
os.rename(tm, test)
quickstart('ssh://x.x.x.x', do_something)
According to the manual, mode w+ truncates (removes all the content from) the file. If you want to open the file for both reading and writing without destroying its contents, use mode r+ or a+.
::edit:: Note, I'm not sure how this works on Windows.
You have to test the file pointer at the beginning of the file using f.seek(0). Or first write to the file then close it then reopen it for reading. But you dont need a file at all - you can as well work on a local variable.
If you are simply planning to write to a file using a python script as show below:
#!/usr/bin/python
count = 1
fo = open('DbCount.txt', 'w')
fo.write(str(count))
#fo.flush()
fo.close()
The Dbcount.txt file which was placed in the same folder as the script(attempting to modify the Dbcount.txt). i dont see any change in the txt file and no error is shown by the interpreter, its very strange, any help ?
first of all, always use the with statement variant, that will always close the file, even on errors:
#!/usr/bin/python
count = 1
with open('DbCount.txt', 'w') as fo:
fo.write(str(count))
then the 'w' overwrites your file each time you write to it. If you want to append, use 'a'.
About your specific problem, did you look only in the directory of your script, or in the current directory you're calling the script from? As you wrote your code, the file's path you write to is relative to where you execute your code from.
try:
import os
count = 1
with open(os.path.join(os.path.dirname(__file__), 'DbCount.txt'), 'w') as fo:
fo.write(str(count))
then it should output DbCount.txt in the same path as your script.
I'm trying to replace a string in all the files within the current directory. for some reason, my temp file ends up blank. It seems my .write isn't working because the secondfile was declared outside its scope maybe? I'm new to python, so still climbing the learning curve...thanks!
edit: I'm aware my tempfile isn't being copied currently. I'm also aware there are much more efficient ways of doing this. I'm doing it this way for practice. If someone could answer specifically why the .write method fails to work here, that would be great. Thanks!
import os
import shutil
for filename in os.listdir("."):
file1 = open(filename,'r')
secondfile = open("temp.out",'w')
print filename
for line in file1:
line2 = line.replace('mrddb2.','shpdb2.')
line3 = line2.replace('MRDDB2.','SHPDB2.')
secondfile.write(line3)
print 'file copy in progress'
file1.close()
secondfile.close()
Just glancing at the thing, it appears that your problem is with the 'w'.
It looks like you keep overwriting, not appending.
So you're basically looping through the file(s),
and by the end you've only copied the last file to your temp file.
You'll may want to open the file with 'a' instead of 'w'.
Your code (correctly indented, though I don't think there's a way to indent it so it runs but doesn't work right) actually seems right. Keep in mind, temp.out will be the replaced contents of only the last source file. Could it be that file is just blank?
Firstly,
you have forgotten to copy the temp file back onto the original.
Secondly:
use sed -i or perl -i instead of python.
For instance:
perl -i -pe 's/mrddb2/shpdb2/;s/MRDDB2/SHPDB2/' *
I don't have the exact answer for you, but what might help is to stick some print lines in there in strategic places, like print each line before it was modified, then again after it was modified. Then place another one after the line was modified just before it is written to the file. Then just before you close the new file do a:
print secondfile.read()
You could also try to limit the results you get if there are too many for debugging purposes. You can limit string output by attaching a subscript modifier to the end, for example:
print secondfile.read()[:n]
If n = 100 it will limit the output to 100 characters.
if your code is actually indented as showed in the post, the write is working fine. But if it is failing, the write call may be outside the inner for loop.
Just to make sure I wasn't really missing something, I tested the code and it worked fine for me. Maybe you could try continue for everything but one specific filename and then check the contents of temp.out after that.
import os
for filename in os.listdir("."):
if filename != 'findme.txt': continue
print 'Processing', filename
file1 = open(filename,'r')
secondfile = open("temp.out",'w')
print filename
for line in file1:
line2 = line.replace('mrddb2.','shpdb2.')
line3 = line2.replace('MRDDB2.','SHPDB2.')
print 'About to write:', line3
secondfile.write(line3)
print 'Done with', filename
file1.close()
secondfile.close()
Also, as others have mentioned, you're just clobbering your temp.out file each time you process a new file. You've also imported shutil without actually doing anything with it. Are you forgetting to copy temp.out back to your original file?
I noticed sometimes it will not print to file if you don't have a file.close after file.write.
For example, this program never actually saves to file, it just makes a blank file (unless you add outfile.close() right after the outfile.write.)
outfile=open("ok.txt","w")
fc="filecontents"
outfile.write(fc.encode("utf-8"))
while 1:
print "working..."
#OP, you might also want to try fileinput module ( this way, you don't have to use your own temp file)
import fileinput
for filename in os.listdir("."):
for line in fileinput.FileInput(filename,inplace=1):
line = line.strip().replace('mrddb2.','shpdb2.')
line = line.strip().replace('MRDDB2.','SHPDB2.')
print line
set "inplace" to 1 for editing the file in place. Set to 0 for normal print to stdout