In my current project, I'm trying to receive a list of values (for now I'm ok with receiving them as a list of strings as that makes a part of the code easier), a name of a file, and iterate through the values to change the value on the file in order to submit many calls to the terminal at once. The problem I have right now is, I believe, that though I'm changing the values, the submitted files are not different from the initial file because I'm failing to realize that I'm not rewriting the file correctly.
1st Part - Input
if __name__ == '__main__':
if len(sys.argv) < 1:
print "Specify the input"
exit(1)
f = sys.argv[1]
list = ast.literal_eval(sys.argv[3])
2nd Part - Rewriting
while i < len(list):
with open(f, 'r+') as file:
programFile = file.read()
for l in range(len(node)):
if i==0:
valuesDic.update({"initialValue":list[i]})
else:
valuesDic.update({list[i-1]:list[i]})
multiValuesChange(programFile, valuesDic)
out_file = open(f, "w")
out_file.write(programFile)
out_file.close()
call(["qsub","-l","h=node10",f])
i=i+1
3rd Part - multiValuesChange
def multiValuesChange(programFile, valuesDic):
rc = re.compile('|'.join(map(re.escape, valuesDic)))
def translate(match):
return valuesDic[match.group(0)]
return rc.sub(translate, programFile)
Thank you.
Your programFile is a string. Strings are immutable. If you want to update it you'll have to collect it back after being processed through the multiValuesChange() function, so do:
programFile = multiValuesChange(programFile, valuesDic)
Related
I want to extract the text between {textblock_content} and {/textblock_content}.
With this script below, only the 1st line of the introtext.txt file is going to be extracted and written in a newly created text file. I don't know why the script does not extract also the other lines of the introtext.txt.
f = open("introtext.txt")
r = open("textcontent.txt", "w")
for l in f.readlines():
if "{textblock_content}" in l:
pos_text_begin = l.find("{textblock_content}") + 19
pos_text_end = l.find("{/textblock_content}")
text = l[pos_text_begin:pos_text_end]
r.write(text)
f.close()
r.close()
How to solve this problem?
Your code actually working fine, assuming you have begin and end block in your line. But I think this is not what you dreamed of. You can't read multiple blocks in one line, and you can't read block which started and ended in different lines.
First of all take a look at the object which returned by open function. You can use method read in this class to access whole text. Also take a look at with statements, it can help you to make actions with file easier and safely. And to rewrite your code so it will read something between {textblockcontent} and {\textblockcontent} we should write something like this:
def get_all_tags_content(
text: str,
tag_begin: str = "{textblock_content}",
tag_end: str = "{/textblock_content}"
) -> list[str]:
useful_text = text
ans = []
# Heavy cicle, needs some optimizations
# Works in O(len(text) ** 2), we can better
while tag_begin in useful_text:
useful_text = useful_text.split(tag_begin, 1)[1]
if tag_end not in useful_text:
break
block_content, useful_text = useful_text.split(tag_end, 1)
ans.append(block_content)
return ans
with open("introtext.txt", "r") as f:
with open("textcontent.txt", "w+") as r:
r.write(str(get_all_tags_content(f.read())))
To write this function efficiently, so it can work with a realy big files on you. In this implementation I have copied our begin text every time out context block appeared, it's not necessary and it's slow down our program (Imagine the situation where you have millions of lines with content {textblock_content}"hello world"{/textblock_content}. In every line we will copy whole text to continue out program). We can use just for loop in this text to avoid copying. Try to solve it yourself
When you call file.readlines() the file pointer will reach the end of the file. For further calls of the same, the return value will be an empty list so if you change your code to sth like one of the below code snippets it should work properly:
f = open("introtext.txt")
r = open("textcontent.txt", "w")
f_lines = f.readlines()
for l in f_lines:
if "{textblock_content}" in l:
pos_text_begin = l.find("{textblock_content}") + 19
pos_text_end = l.find("{/textblock_content}")
text = l[pos_text_begin:pos_text_end]
r.write(text)
f.close()
r.close()
Also, you can implement it through with context manager like the below code snippet:
with open("textcontent.txt", "w") as r:
with open("introtext.txt") as f:
for line in f:
if "{textblock_content}" in l:
pos_text_begin = l.find("{textblock_content}") + 19
pos_text_end = l.find("{/textblock_content}")
text = l[pos_text_begin:pos_text_end]
r.write(text)
I want to be able to add a specific character into my file, using python code.
I have attempted using read functions, meaning lists, but those come up with an error of "TypeError: 'builtin_function_or_method"
I believe this means that python can not write a character into a specific place using the list function
Incorrect way:
file: 1)5
Code:
while true:
with open ('file','w') as f:
f.writeline[0]=+1
with open ('file','r') as f:
fc = f.read()
print (fc)
Expected output:
5,6,7,8,9,10,11,12,13,14,15....
I assumed that this line of code would increase the five until I stopped the program, but instead it sent the error code described earlier. Is there a way to write the code so that it does it as expected?
Basically, you would need to build a function to update a single character. I think this would work, but I literally wrote it in like three minutes, so take caution...
def write_at_index(filename,y_pos,x_pos,character):
"""Write a character 'character' at the given index"""
lines = 0 //begin lines outside scope of the with statement.
with open(filename,"r") as file:
lines = file.readlines()
if len(lines)<y_pos:
raise Exception('y pos out of bounds')
if len(lines[y_pos]) < x_pos
raise Exception('x_pos out of bounds')
lines[y_pos][x_pos] = character
with open(filename,"w") as file:
file.writelines(lines)
The first, your code will have an infinite loop:
while True: Do you have any check variable?
The second, I don't think this one can work for you: f.writeline[0]=+1
I'm not sure that my recommend code can help you fix your issue, but if it doesn't match your idea, please comment it.
check = True
# file = '1)5'
add_val = 5
while check:
open('file', 'w').write(add_val + ",")
add_val += 1
if add_val > 20: # condition to break the while loop
check = False
f = open('file','r').read()
print (f)
I'm trying to get the below function running from the command line by simply using
python filename.py
However, it isn't doing what I want.
Could someone please help me out with this? I'm sure I'm missing something very simple...
inFile = ""
inFile = raw_input("Enter the File Name: ")
x = open(inFile, 'w')
def summation(x):
sum = 0
for i in x:
sum = sum + i
return sum
if __name__ == "__main__":
print(summation(x))
Hopefully it's fairly self explanatory what I'm trying to achieve, but in case it's not...
I'm asking for a raw_input; this will be a text file full of numbers (each on it's own line). The file should be fed into the variable x which is then used in the summation function. Finally, with a for loop each value is summed and the sum is returned (and printed in terminal).
There are two problems:
You're opening the file in write mode. This deletes all the contents of the file. Drop the "w" parameter.
You can't add strings (as read from the file) to an integer. You need to convert them to integers first: sum += int(i)
Also, you should close the file after you've read its contents. And the line infile = "" is unnecessary.
A more pythonic version...
def line_to_int(line):
line = line.strip()
if not line:
# handles the case of empty lines
return 0
return int(line)
def sumfile(f):
return sum(line_to_int(line) for line in f)
if __name__ == "__main__":
fname = raw_input("Enter the File Name: ").strip()
with open(fname) as f:
print(sumfile(f))
or even more simple as long as you don't plan on adding error handling around the call to int(line) (thanks Jon Clements):
if __name__ == "__main__":
fname = raw_input("Enter the File Name: ").strip()
with open(fname) as f:
print(sum(int(line.strip() or 0) for line in f))
I am currently keeping high scores into a text file called "score.txt". The prgoram works fine, updating the file with the new high scores as normal. Except that every time the program updates the file, there is always one blank line before the first high score, creating an error when I try to save the scores the next time. The code:
scores_list = []
score = 10
def take_score():
# Save old scores into list
f = open("score.txt", "r")
lines = f.readlines()
for line in lines:
scores_list.append(line)
print scores_list
f.close()
take_score()
def save_score():
# Clear file
f = open("score.txt", "w")
print >> f, ""
f.close()
# Rewrite scores into text files
w = open("score.txt", "a")
for i in range(0, len(scores_list)):
new_string = scores_list[i].replace("\n", "")
scores_list[i] = int(new_string)
if score > scores_list[i]:
scores_list[i] = score
for p in range(0, len(scores_list)):
print >> w, str(scores_list[p])
print repr(str(scores_list[p]))
save_score()
The problem mentioned happens in the save_score() function. I have tried this related question: Removing spaces and empty lines from a file Using Python, but it requires I open the file in "r" mode. Is there a way to accomplish the same thing except when the file is opened in "a" mode (append)?
You are specifically printing an empty line as soon as you create the file.
print >> f, ""
You then append to it, keeping the empty line.
If you just want to clear the contents every time you run this, get rid of this:
# Clear file
f = open("score.txt", "w")
print >> f, ""
f.close()
And modify the opening to this:
w = open("score.txt", "w")
The 'w' mode truncates already, as you were already using. There's no need to truncate, write an empty line, close, then append lines. Just truncate and write what you want to write.
That said, you should use the with construct and file methods for working with files:
with open("score.txt", "w") as output: # here's the with construct
for i in xrange(len(scores_list)):
# int() can handle leading/trailing whitespace
scores_list[i] = int(scores_list[i])
if score > scores_list[i]:
scores_list[i] = score
for p in xrange(len(scores_list)):
output.write(str(scores_list[p]) + '\n') # writing to the file
print repr(str(scores_list[p]))
You will then not need to explicitly close() the file handle, as with takes care of that automatically and more reliably. Also note that you can simply send a single argument to range and it will iterate from 0, inclusive, until that argument, exclusive, so I've removed the redundant starting argument, 0. I've also changed range to the more efficient xrange, as range would only be reasonably useful here if you wanted compatibility with Python 3, and you're using Python 2-style print statements anyway, so there isn't much point.
print appends a newline to what you print. In the line
print >> f, ""
You're writing a newline to the file. This newline still exists when you reopen in append mode.
As #Zizouz212 mentions, you don't need to do all this. Just open in write mode, which'll truncate the file, then write what you need.
Your opening a file, clearing it, but then you open the same file again unnecessarily. When you open the file, you print a newline, even if you don't think so. Here is the offending line:
print >> f, ""
In Python 2, it really does this.
print "" + "\n"
This is because Python adds a newline at the end of the string to each print statement. To stop this, you could add a comma to the end of the statement:
print "",
Or just write directly:
f.write("my data")
However, if you're trying to save a Python data type, and it does not have to be human-readable, you may have luck using pickle. It's really simple to use:
def save_score():
with open('scores.txt', 'w') as f:
pickle.dump(score_data, f):
It is not really answer for question.
It is my version of your code (not tested). And don't avoid rewriting everything ;)
# --- functions ---
def take_score():
'''read values and convert to int'''
scores = []
with open("score.txt", "r") as f
for line in f:
value = int(line.strip())
scores.append(value)
return scores
def save_score(scores):
'''save values'''
with open("score.txt", "w") as f
for value in scores:
write(value)
write("\n")
def check_scores(scores, min_value):
results = []
for value in scores:
if value < min_value:
value = min_value
results.append(value)
return resulst
# --- main ---
score = 10
scores_list = take_score()
scores_list = check_scores(scores_list, score)
save_score(scores_list)
So when i write this chunk of code separately, it works fine but when i combine them together it give me typeError. Why is this happen? I don't get it when i wrote them separately it works fine. thanks in advance :)
def printOutput(start, end, makeList):
if start == end == None:
return
else:
print start, end
with open('OUT'+ID+'.txt','w') as outputFile:#file for result output
for inRange in makeList[(start-1):(end-1)]:
outputFile.write(inRange)
with open(outputFile) as file:
text = outputFile.read()
with open('F'+ID+'.txt', 'w') as file:
file.write(textwrap.fill(text, width=6))
Your problem is at this line:
with open(outputFile) as file:
outputFile is a file object (which is already open). The open function wants a string (or something like it) which is the name of a file to open.
If you want to get the text back, you can always outputFile.seek(0) and then outputFile.read() again. (Of course, you'll have to open in r+ mode for this to work.)
Perhaps an even better way to do this would be:
with open('OUT'+ID+'.txt','w') as outputFile:#file for result output
text=''.join(makeList[(start-1):(end-1)])
outputFile.write(text)
with open('F'+ID+'.txt', 'w') as ff:
ff.write(textwrap.fill(text, width=6)) #Version of above file with text wrapped to 6 chars.
EDIT
This should work:
def printOutput(start, end, makeList):
if start == end == None:
return
else:
print start, end
with open('OUT'+ID+'.txt','w') as outputFile:#file for result output
text=''.join(makeList[(start-1):(end-1)])
outputFile.write(text)
with open('F'+ID+'.txt', 'w') as ff:
ff.write(textwrap.fill(text, width=6)) #Version of above file with text wrapped to 6 chars.