How to set range index in for loop - python

Im creating a job-script to use dayli, and trying to tranform a line-sequential txt to a data-line txt.
Ive already reach the index of header lines and also get the 'laborer code' for each header.
for line_no, line in enumerate(data):
if line[0:10] == 'FUNCIONARI':
code = int(line[11:18])
# print(line_no)
else:
line_no = -1
for line in range(index=line_no, 32, 1):
line += code
print(line)
Pycharm return that: "SyntaxError: positional argument follows keyword argument"
How could I repeat the code gattered upper, to the end of next 32 lines?

Solved!
code = 0
for line in data:
if line[:10] == 'FUNCIONARIO':
code = line[11:16]
line = code, line
Any time line receives the code. So when the code gets new number, its goes down in line till next change.

Related

Reading and adding numbers from a text document in Python

I have a text document with a list of numbers, I need to have a function that reads all of them, and adds them together so then I can average them all out. I'm able to print the individual numbers and count the total numbers but not add the actual numbers together. Currently my code gives me "ValueError: invalid literal for int() with base 10: ''"
def CalcAverage():
scoresFile = open("data.txt", "r")
line = scoresFile.readline()
scoreCounter = 1
scoreTotal = 0
while line != "":
line = scoresFile.readline()
total = int(line) + int(line)
scoreCounter = int(scoreCounter) + 1
print(total)
scoresFile.close()
Assuming this is the error you're getting, replicated in the REPL:
>>> int("")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''
Then the issue is that you're trying to cast an empty string into an int. This will naturally result in an error, and is a common one if you have empty lines in your file.
You sorta check against this:
while line != "":
But the issue with this is where you assign line: immediately after this check. While your first line value will be checked, it will be immediately replaced by a new line = scoresFile.readline().
Thus, as you enter your while loop, line is the first line in your file. Then, it will assign the second line to line, dropping the first line's value. This will cause two different errors - one where you attempt in the following line to cast an empty string to an int, and one where you are ignoring the value of your first line. You need to alter how you do your check.
def calc_average():
with open("data.txt", "r") as scores:
counter = 0
total = 0
for line in scores.readlines(): # Returns the lines as a list
total += int(line)
counter += 1
print(f"{total=} {counter=}")
Note these following good-hygeine practices in Python:
Name your variables and functions using snake case.
Use with to open a file. This calls close automatically, so you don't risk forgetting it.

Python - Extracting data from a text file (list index out of range)

I created a script to extract weekdays from lines in a text file (email data) starting with 'From:'. I successfully did so and then as part of an exercise I need to modify the text file such that it causes a bug. To do this I added an extra line 'From' to line 1 of the text file (image below) which causes the original code to not work and throw an error. To debug the script, I added an if-statement to first check whether the array is greater than length of 0 to proceed with the print statement, although this does not work. What is the most efficient way of resolving this error?
Original code:
fhand = open('mbox-short.txt')
count = 0
for line in fhand:
if line == '': continue
line = line.rstrip()
words = line.split()
if words == []: continue
if words[0] != 'From' : continue
print(words[2])
Modified:
Code:
fhand = open('mbox-short (will fail).txt')
count = 0
for line in fhand:
if line == '': continue
line = line.rstrip()
words = line.split()
if words == []: continue
if words[0] != 'From' : continue
if len(words) >0:
print(words[2])
OUTPUT:
File "C:\Users\User\Desktop\Chapter 8\8.2 - #2.py", line 9, in <module>
print(words[2])
IndexError: list index out of range
Thank you Aditya, the issue was that lines containing less than 3 words were being stored in the list (these could not possibly contain the day). As a result, when index 3 was referenced, it threw an error.

First of two blocks of code of reading from a file not executing in python

As part of an assignment I'm writing an assembler in python that takes simplified assembly language and outputs binary machine language. Part of my code is below, where I'm reading from the assembly code in two passes. The first pass (the first line of with open(filename, "r") as asm_file) in the first block of reading from the file asm_file doesn't seem to be executing. The second one is executing fine, well it's not outputting the correct binary because the first block doesn't seem to be running correctly or at all. Am I using the "with open(filename. "r") as file:" correctly? What am I missing? Thanks in advance.
For completeness an input file is given below the code:
if __name__ == "__main__":
#fill Symbol Table and C instruction Tables
symbol_table = symbolTable()
symbol_table.initialiseTable()
comp_table = compTable()
comp_table.fillTable()
dest_table = destTable()
dest_table.fillTable()
jump_table = jumpTable()
jump_table.fillTable()
#import the file given in the command line
filename = sys.argv[-1]
#open output_file
output_file = open('output.hack', 'w')
#open said file and work on contents line by line
with open(filename, "r") as asm_file: ##### This one doesn't seem to run because
#1st pass of input file ##### The print command below doesn't output anything
num_instructions = -1
for line in asm_file:
#ignoring whitespace and comments
if line != '\n' and not line.startswith('//'):
num_instructions += 1
#remove in-line comments
if '//' in line:
marker, line = '//', line
line = line[:line.index(marker)].strip()
#search for beginning of pseudocommand
if line.startswith('('):
num_instructions -= 1
label = line.strip('()')
address = num_instructions + 1
symbol_table.addLabelAddresses(label, address)
print(num_instructions) ###### This print command doesn't output anything
with open(filename, "r") as asm_file:
#2nd pass of input file
for line in asm_file:
#ignoring whitespace and comments
if line != '\n' and not line.startswith('//') and not line.startswith('('):
#remove in-line comments
if '//' in line:
marker, line = '//', line
line = line[:line.index(marker)].strip()
#send each line to parse function to unpack into its underlying fields
instruction = parseLine(line.strip(' \n'))
inst = Instruction(instruction)
binary_string = inst.convertToBin()
#write to output file
output_file.write(binary_string +'\n')
output_file.close()
An input file example:
// This file is part of www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/06/max/Max.asm
// Computes R2 = max(R0, R1) (R0,R1,R2 refer to RAM[0],RAM[1],RAM[2])
#R0
D=M // D = first number
#R1
D=D-M // D = first number - second number
#OUTPUT_FIRST
D;JGT // if D>0 (first is greater) goto output_first
#R1
D=M // D = second number
#OUTPUT_D
0;JMP // goto output_d
(OUTPUT_FIRST)
#R0
D=M // D = first number
(OUTPUT_D)
#R2
M=D // M[2] = D (greatest number)
(INFINITE_LOOP)
#INFINITE_LOOP
0;JMP // infinite loop
Your problem seems to be that your code checks if a line starts with a (, but in the assembly it has a tab before an instruction so that it doesn't work. You should probably do a line.strip() after your first if statement like so
with open(filename, "r") as asm_file:
num_of_instructions = -1
for line in asm_file
if line != "\n":
line.strip()
#rest of code
Incidentally, is the print statement supposed to execute every time it finds a line? Because if it doesn't, you should put it after the for loop. That is why it is not outputting anything
Edit: As #TimPeters says, the print statement will also only execute if it starts with an open bracket and has a comment in it
In the first with, starting with
#search for beginning of pseudocommand
are you quite sure you don't want that and the following lines dedented a level?
As is, the only way to get to your print is if a line satisfies both
if '//' in line:
and
if line.startswith('('):
There are no lines in your input file satisfying both, so the print never executes.
In the second with, there are only two indented lines after its
if '//' in line:

Re-ordering text file - Python

I must re-order an input file and then print the output to a new file.
This is the input file:
The first line never changes.
The second line was a bit much longer.
The third line was short.
The fourth line was nearly the longer line.
The fifth was tiny.
The sixth line is just one line more.
The seventh line was the last line of the original file.
This is what the output file should look like:
The first line never changes.
The seventh line was the last line of the original file.
The second line was a bit much longer.
The sixth line is just one line more.
The third line was short.
The fifth was tiny.
The fourth line was nearly the longer line.
I have code already that reverse the input file and prints it to the output file which looks like this
ifile_name = open(ifile_name, 'r')
lines = ifile_name.readlines()
ofile_name = open(ofile_name, "w")
lines[-1] = lines[-1].rstrip() + '\n'
for line in reversed(lines):
ofile_name.write(line)
ifile_name.close()
ofile_name.close()
Is there anyway I can get the desired format in the text file while keeping my reverse code?
Such as print the first line of the input file, then reverse and print that line, the print the second line of the input file, then reverse and print that line etc.
Sorry if this may seem unclear I am very new to Python and stack overflow.
Thanks in advance.
This is a much elegant solution I believe if you don't care about the list generated.
with open("ifile_name","r") as f:
init_list=f.read().strip().splitlines()
with open("result.txt","a") as f1:
while True:
try:
f1.write(init_list.pop(0)+"\n")
f1.write(init_list.pop()+"\n")
except IndexError:
break
ifile_name = "hello/input.txt"
ofile_name = "hello/output.txt"
ifile_name = open(ifile_name, 'r')
lines = ifile_name.readlines()
ofile_name = open(ofile_name, "w")
lines[-1] = lines[-1].rstrip() + '\n'
start = 0
end = len(lines) - 1
while start < end:
ofile_name.write(lines[start])
ofile_name.write(lines[end])
start += 1
end -= 1
if start == end:
ofile_name.write(lines[start])
ifile_name.close()
ofile_name.close()
use two pivots start and end to point which line to write to the file.
once start == end, write the middle line to the file

How to grab a chunk of data from a file?

I want to grab a chunk of data from a file. I know the start line and the end line. I wrote the code but its incomplete and I don't know how to solve it further.
file = open(filename,'r')
end_line='### Leave a comment!'
star_line = 'Kill the master'
for line in file:
if star_line in line:
??
startmarker = "ohai"
endmarker = "meheer?"
marking = False
result = []
with open("somefile") as f:
for line in f:
if line.startswith(startmarker): marking = True
elif line.startswith(endmarker): marking = False
if marking: result.append(line)
if len(result) > 1:
print "".join(result[1:])
Explanation: The with block is a nice way to use files -- it makes sure you don't forget to close() it later. The for walks each line and:
starts outputting when it sees a line that starts with 'ohai' (including that line)
stops outputting when it sees a line that starts with 'meheer?' (without outputting that line).
After the loop, result contains the part of the file that is needed, plus that initial marker. Rather than making the loop more complicated to ignore the marker, I just throw it out using a slice: result[1:] returns all elements in result starting at index 1; in other words, it excludes the first element (index 0).
Update to reflect add partial-line matches:
startmarker = "ohai"
endmarker = "meheer?"
marking = False
result = []
with open("somefile") as f:
for line in f:
if not marking:
index = line.find(startmarker)
if index != -1:
marking = True
result.append(line[index:])
else:
index = line.rfind(endmarker)
if index != -1:
marking = False
result.append(line[:index + len(endmarker)])
else:
result.append(line)
print "".join(result)
Yet more explanation: marking still tells us whether we should be outputting whole lines, but I've changed the if statements for the start and end markers as follows:
if we're not (yet) marking, and we see the startmarker, then output the current line starting at the marker. The find method returns the position of the first occurrence of startmarker in this case. The line[index:] notation means 'the content of line starting at position index.
while marking, just output the current line entirely unless it contains endmarker. Here, we use rfind to find the rightmost occurrence of endmarker, and the line[...] notation means 'the content of line up to position index (the start of the match) plus the marker itself.' Also: stop marking now :)
if reading the whole file is not a problem, I would use file.readlines() to read in all the lines in a list of strings.
then you can use list_of_lines.index(value) to find the indices of the first and last line, and then select all the lines between these two indices.
First, a test file (assuming Bash shell):
for i in {0..100}; do echo "line $i"; done > test_file.txt
That generates a file a 101 line file with lines line 0\nline 1\n ... line 100\n
This Python script captures the line between and including mark1 up to and not including mark2:
#!/usr/bin/env python
mark1 = "line 22"
mark2 = "line 26"
record=False
error=False
buf = []
with open("test_file.txt") as f:
for line in f:
if mark1==line.rstrip():
if error==False and record==False:
record=True
if mark2==line.rstrip():
if record==False:
error=True
else:
record=False
if record==True and error==False:
buf.append(line)
if len(buf) > 1 and error==False:
print "".join(buf)
else:
print "There was an error in there..."
Prints:
line 22
line 23
line 24
line 25
in this case. If both marks are not found in the correct sequence, it will print an error.
If the size of the file between the marks is excessive, you may need some additional logic. You can also use a regex for each line instead of an exact match if that fits your use case.

Categories