Below is the code in question:
def search():
name = enter.get()
print(name)
name = name.lower()
data = open("moredata.txt")
found = False
results = str()
for line in data:
record = line.split("|")
record[0] = str(record[0])
print("'" + name + "'" "---" + "'" + record[0] + "'")
if record[0] == name:
found = True
line = str(line)
results += line
results = str(results).lstrip(' ')
continue
else:
found = False
continue
if not found:
print("No results found")
else:
print("These items match your search query:\n")
print(results)
# print(results)
print('\n---------------------------------\n')
In the text file I am using, pieces of information are separated by '|' and the function splits each piece into an array (I think?) and compares just the first value to what I put in the search bar.
I have used other text files with the same exact function, it works just fine: it verifies that the two strings are equal and then displays the entire line of the text file corresponding to what I wanted. However, when I search "a" which should register as equal to "a" from the line a|a|a|a|a|a in my text file, it doesn't. I know this is going to bite me later if I don't figure it out and move on because it works in some cases.
The line
print("'" + name + "'" "---" + "'" + record[0] + "'")
results in
'a'---'a'
'a'---'a'
'a'---'b'
when compared to lines
a|a|a|a|a|a
a|a|a|a|a|a
b|b|b|b|b|b
There are no empty lines between results, and both variable types are str().
The continue in your if statement in the loop is what's causing the problem as it should be a break.
Your program is finding it, but it's then being overwritten by the last iteration. Once your program has found, you should either never set found back to false, or preferably just cease the iteration altogether.
I would wager the other files you've tested with all end with the name that you were looking for, and this one is causing a problem because the name you're looking for isn't at the end.
Additionally, though technically not a problem, the other continue under the else in the for loop isn't necessary.
Your found variable is being overwritten on each iteration of the loop.
Therefore it will only be True if the last result matches.
You don't actually need your found variable at all. If there are results, your results variable will have data in it and you can test for that.
Related
So I am trying to do the MacDonald challenge.Given a function with the parameter "name", return the MacDonald version of it, the 1st and 4th letter being capitalized.
If I try the code without any if else and I pass in just "mac" an error occurs.So I said that if the length of name is less than 5 letters, print out that name is too short.Otherwise, do the macdonald version.
However, for some reason len() gives out an error here.
def old_macdonald(name):
firstLetter = name[0].capitalize()
fourthLetter = name[3].capitalize()
inBetween = name[1:3]
last = name[4:]
newName = firstLetter + inBetween + fourthLetter + last
if len(newName) < 4:
print("name is too short.")
else:
print(newName)
old_macdonald("mac")
I don't think len is throwing the exception, but just as the version without if condition the string manipulation does.
Do the string manipulation in the else part of your code to avoid the exception.
Following Jens' advice, I included the if check above everything else (since you want to terminate the function if the name is too short) and returned in the if-check to break end the function.
def old_macdonald(name):
if len(name)< 4:
print("name is too short.")
return
firstLetter = name[0].capitalize()
fourthLetter = name[3].capitalize()
inBetween = name[1:3]
last = name[4:]
newName = firstLetter + inBetween + fourthLetter + last
print(newName)
old_macdonald("mac")
old_macdonald("macdonald")
Here is the result
You are still trying to perform the same operations anyway, len is not throwing you an error, the above part of the code is giving you error.
Simply move your code to the else part of function and you should be fine. The reason you need to do this is because you need to check first, and then perform, instead of performing and then checking.
beginning python programmer here. I am currently stuck with writing a small python script that would open a txt source file, find a specific number in that source file with a regular expression (107.5 in this case) and ultimately replace that 107.5 with a new number. the new number comes from a second txt file which contains 30 numbers. Each time a number has been replaced, the script uses the next number for its replacement. Although the command prompt does seem to print a successfull find and replace, "an IndexError: list index out of range" occurs after the 30th loop...
My hunge is that I somehow have to limit my loop with something like "for i in range x". However I am not sure which list this should be and how I can incorporate that loop limitation in my current code. Any help is much appreciated!
nTemplate = [" "]
output = open(r'C:\Users\Sammy\Downloads\output.txt','rw+')
count = 0
for line in templateImport:
priceValue = re.compile(r'107.5')
if priceValue.sub(pllines[count], line) != None:
priceValue.sub(pllines[count], line)
nTemplate.append(line)
count = count + 1
print('found a match. replaced ' + '107.5 ' + 'with ' + pllines[count] )
print(nTemplate)
else:
nTemplate.append(line)
The IndexError is raised because you are incrementing count in each iteration of the loop, but haven't added an upper limit based on how many values the pllines list actually contains. You should break out of the loop when it reaches len(pllines) in order to avoid the error.
Another issue which you may not have noticed is with your usage of the re.sub() method. It returns a new string with the appropriate replacements, and does not modify the original.
If the pattern doesn't exist in the string, it'll return the original itself. So your nTemplate list probably never had any of the replaced strings appended to it. Unless you need to do some other actions if the pattern was found in the line, you can do away with the if condition (as I have in the example below).
Since the priceValue object is the same for all lines, it can be moved outside the loop.
The following code should work:
nTemplate = [" "]
output = open(r'C:\Users\Sammy\Downloads\output.txt','rw+')
count = 0
priceValue = re.compile(r'107.5')
for line in templateImport:
if count == len(pllines):
break
nTemplate.append(priceValue.sub(pllines[count], line))
count = count + 1
print(nTemplate)
Hello I am having a KeyError when searching through a huge file with multiple serial numbers. The issue occurs when ever I am searching through the file and input a serial number that appears twice within the file. I want to search through this text file and print out the serial numbers I need or the user inputs.
This is the error:
if item[param] != correct:
KeyError: 'APN'
Here is a text example of the file I am searching through:
500,SHOWALL
APN=" "
APU=" "
APP=" "
IPD="127.0.0.1"
DSP=1710
IPU="127.0.0.1"
VWD="2"
600,SHOWALL
APN=""
APU=" "
APP=" "
IPD="127.0.0.1"
DSP=1710
IPU="127.0.0.1"
VWD="2"
700,SHOWALL
APN=" "
APU=" "
APP=" "
IPD="127.0.0.1"
DSP=1710
IPU="127.0.0.1"
VWD="2"
500,SHOWALL
APN=""
APU=" "
APP=" "
IPD="127.0.0.1"
DSP=1710
IPU="127.0.0.1"
VWD="2"
since 500 appears twice in the file it will run into a KeyError.
Here is an example of my code:
def process(infile, outfile, keywords):
keys = [[k[0], k[1], 0] for k in keywords ]
endk = None
with open(infile, "rb") as fdin:
with open(outfile, "ab") as fdout:
fdout.write("<" + words + ">" + "\n")
for line in fdin:
if endk is not None:
fdout.write(line)
if line.find(endk) >= 0:
fdout.write("\n")
endk = None
else:
for k in keys:
index = line.find(k[0])
if index >= 0:
fdout.write(line[index + len(k[0]):].lstrip())
endk = k[1]
k[2] += 1
if endk is not None:
raise Exception(endk + " not found before end of file")
return keys
This is the definition process I use for the input file, output file, and the keywords to search through the file. This is the output portion of the code:
while (count < (len(setNames))):
for number, item in enumerate(lst, 0):
print setNames[count]
for param, correct in correct_parameters.items():
if item[param] != correct:
print('{} = {} which is incorrect'.format(param, item[param]))
with open(compareResults, "ab") as fdout:
fdout.write('{}'.format(setNames[count]) + " " + '{} = {} which is incorrect'.format(param, item[param])+ '\n')
count += 1
My goal would be to some how allow the program to output the result twice if the serial number appears twice or more. So even if 500 appears two or more times within my text file. I still want it to print correct all the 500 results.
Here is a link to my full code. I did not post the full thing because it is very convoluted and needs some cleaning up to do before anything.
http://pastebin.com/aCe9N8vW
If any more information is need I will post below.
It sounds like you were not expecting a KeyError to occur. If that is the case, then using item.get() may only hide the error. Consider using try/except:
try:
if item[param] != correct:
report_incorrect()
except KeyError:
print('Expected key {}'.format(param))
Really you should go back through the code and determine why the key doesn't exist.
I attempted to look at the link you provided, but the code is not yet organized enough for me to easily read. It would help to provide some comments at the top about what it is supposed to do. For example,
"""This code reads an input log file and a configuration file.
For each serial number in the configuration file, it outputs how
many times it occurs in the log file.
"""
Also it would help to organize more things into functions and perhaps classes, again with comments about the goal of each. Perhaps when the code is cleaned up, the problem will go away.
You can try like this,
if item.get(param) != correct:
KeyError:
Raised when a mapping (dictionary) key is not found in the set of existing keys.
If you don't want to have an exception, you can use the get() method
I am new to python and with this task I'm trying to learn it. I'd like to get information out of a DNS zone file. The DNS file has the following entries:
something 600 A 192.168.123.45
600 A 192.168.123.46
someelse CNAME something
anotherone A 192.168.123.47
nextone CNAME anotherone
anotherone TXT ( "te asd as as d" )
The goal is to grab the hostnames and IF there is a coresponding TXT entry, I'd like to get the information for that entry as well.
So I started to just work through the file, if I would describe the entries, the Record type is either at [2] or [1] and right after it, I got the IP. So I have something like this for now:
for line in data:
word = line.split()
if len(word) > 2:
if "CNAME" == word[2]:
rectype = "CNAME"
arecord = word[3].replace('.domain.com.', '')
print rectype + " " + arecord
if "CNAME" == word[1]:
rectype = "CNAME"
arecord = word[2].replace('.domain.com.', '')
print rectype + " " + arecord
if "A" == word[2]:
rectype = "A"
print rectype + " " + word[3]
if "A" == word[1]:
rectype = "A"
print rectype + " " + word[2]
okay, so far so good.. but now if I like to get that corresponding TXT record, do I need to work through every line in the document for each line or is their any easier and more efficiernt way to do that?
Part of the beauty of Python is you can write code that reads like English and it uses intuitive operators.
You have a lot of duplicated code. In your example, we can see that anytime a "keyword" pops up, such as A or CNAME then you simply take the next token. Here, I used the in Python keyword which checks if an element is in a collection of some sort. This is a boolean, so if it returns true then I take the next element, ie, tokens[tokens.index(keyword) + 1].
Similarly, in can also be used for string and substring searches. I check to see if "TXT" is in the current line, and if it is, I assume you want everything after it? I use a splice operator to specify the range.
line[line.index("TXT") + 3:] means that I want everything in line after the index line.index("TXT") + 3.
KEYWORDS = ["CNAME", "A"]
for line in data:
tokens = line.split()
if len(tokens) > 2:
record = ""
for keyword in KEYWORDS:
if keyword in tokens:
record = keyword + " " + tokens[tokens.index(keyword) + 1]
if "TXT" in line:
txt_data = line[line.index("TXT") + 3:]
record += "TXT: " + txt_data
print record
I'd recommend you build a dictionary whose keys are identifiers ("anotherone" would be an example from your sample) and whose values are strings (or maybe a list of strings - I'm rusty on DNS and am not sure if multiples are possible).
As you encounter CNAME and A records, add the identifiers as keys into the dictionary and initialize their corresponding values as empty lists. Then when you hit a line with "TXT" in it, lookup that identifier in the dictionary and add the line as value.
I have a file i am trying to replace parts of a line with another word.
it looks like bobkeiser:bob123#bobscarshop.com:0.0.0.0.0:23rh32o3hro2rh2:234212
i need to delete everything but bob123#bobscarshop.com, but i need to match 23rh32o3hro2rh2 with 23rh32o3hro2rh2:poniacvibe , from a different text file and place poniacvibe infront of bob123#bobscarshop.com
so it would look like this bob123#bobscarshop.com:poniacvibe
I've had a hard time trying to go about doing this, but i think i would have to split the bobkeiser:bob123#bobscarshop.com:0.0.0.0.0:23rh32o3hro2rh2:234212 with data.split(":") , but some of the lines have a (:) in a spot that i don't want the line to be split at, if that makes any sense...
if anyone could help i would really appreciate it.
ok, it looks to me like you are using a colon : to separate your strings.
in this case you can use .split(":") to break your strings into their component substrings
eg:
firststring = "bobkeiser:bob123#bobscarshop.com:0.0.0.0.0:23rh32o3hro2rh2:234212"
print(firststring.split(":"))
would give:
['bobkeiser', 'bob123#bobscarshop.com', '0.0.0.0.0', '23rh32o3hro2rh2', '234212']
and assuming your substrings will always be in the same order, and the same number of substrings in the main string you could then do:
firststring = "bobkeiser:bob123#bobscarshop.com:0.0.0.0.0:23rh32o3hro2rh2:234212"
firstdata = firststring.split(":")
secondstring = "23rh32o3hro2rh2:poniacvibe"
seconddata = secondstring.split(":")
if firstdata[3] == seconddata[0]:
outputdata = firstdata
outputdata.insert(1,seconddata[1])
outputstring = ""
for item in outputdata:
if outputstring == "":
outputstring = item
else
outputstring = outputstring + ":" + item
what this does is:
extract the bits of the strings into lists
see if the "23rh32o3hro2rh2" string can be found in the second list
find the corresponding part of the second list
create a list to contain the output data and put the first list into it
insert the "poniacvibe" string before "bob123#bobscarshop.com"
stitch the outputdata list back into a string using the colon as the separator
the reason your strings need to be the same length is because the index is being used to find the relevant strings rather than trying to use some form of string type matching (which gets much more complex)
if you can keep your data in this form it gets much simpler.
to protect against malformed data (lists too short) you can explicitly test for them before you start using len(list) to see how many elements are in it.
or you could let it run and catch the exception, however in this case you could end up with unintended results, as it may try to match the wrong elements from the list.
hope this helps
James
EDIT:
ok so if you are trying to match up a long list of strings from files you would probably want something along the lines of:
firstfile = open("firstfile.txt", mode = "r")
secondfile= open("secondfile.txt",mode = "r")
first_raw_data = firstfile.readlines()
firstfile.close()
second_raw_data = secondfile.readlines()
secondfile.close()
first_data = []
for item in first_raw_data:
first_data.append(item.replace("\n","").split(":"))
second_data = []
for item in second_raw_data:
second_data.append(item.replace("\n","").split(":"))
output_strings = []
for item in first_data:
searchstring = item[3]
for entry in second_data:
if searchstring == entry[0]:
output_data = item
output_string = ""
output_data.insert(1,entry[1])
for data in output_data:
if output_string == "":
output_string = data
else:
output_string = output_string + ":" + data
output_strings.append(output_string)
break
for entry in output_strings:
print(entry)
this should achieve what you're after and as prove of concept will print the resulting list of stings for you.
if you have any questions feel free to ask.
James
Second edit:
to make this output the results into a file change the last two lines to:
outputfile = open("outputfile.txt", mode = "w")
for entry in output_strings:
outputfile.write(entry+"\n")
outputfile.close()