I'm creating a program that saves his infos as encoded infos using a method that I created.
Basically when I start the program it creates two variables,
one is the alphabet (uppercase, lowercase, digits, ...)
the other is the exact same except that I use a random.shuffle() to randomize it.
That's the "key" to a "key" I give it a random number using random.randint(1000000000,9999999999) and this number I call it the name of the "key".
All the keys and theirs name are stored in a file.
In the program you have the opportunity to write something like a name, that name is going to be encrypted using the key that is generated when I start the program, then stored in a file along with the name of the key.
(Note that the keys always have a different name, the encrypted data may has been encrypted using many times the same key then stored in another file).
I read from the key file first
{NOTE: the keys are stored using a \n pattern, example
file.write(f'{key}\n{key_name}\n') }
using my method the length will always be divisible for 2 so I use a variable initialized before the for cycle and increase it along with the cycle, meanwhile I use that same variable to read from the list (the result of reading the key file) and assign a name to a key, example:
{4819572: 'varoabIfokdbKjs3918', 40101846: 'opqihduqv', 8291073: 'hqowirhwip', ...}
My keys are 354 chars long so those are a really small example.
Here is the code described above
sep = os.sep
Ot = platform.system()
file_name = os.path.basename(__file__)
path_to_file = __file__.replace(file_name, '')
with open(f'{path_to_file}database{sep}history.dll', 'r', encoding='utf-8') as file:
keys = file.readlines()
num = 0
archive = {}
for _ in range(int(len(keys)/2)):
key_name = str(keys[num+1]).replace('\n','')
key = str(keys[num]).replace('\n','')
archive[int(key_name)] = key
num =+ 2
num1 = 0
num2 = 0
After this I use the key_name to get the key which is used in a decrypt function along with the encrypted text.
The problem is that even if I have 16 keys in the dictionary there are only 2. I really don't know how to resolve this or why this is appending.
You have writen "num =+ 2", I think you wanted write "num += 2"
Related
I'm working on cs50's pset6, DNA, and I want to read a csv file that looks like this:
name,AGATC,AATG,TATC
Alice,2,8,3
Bob,4,1,5
Charlie,3,2,5
But the problem is that dictionaries only have a key, and a value, so I don't know how I could structure this. What I currently have is this piece of code:
import sys
with open(argv[1]) as data_file:
data_reader = csv.DictReader(data_file)
And also, my csv file has multiple columns and rows, with a header and the first column indicating the name of the person. I don't know how to do this, and I will later need to access the individual amount of say, Alice's value of AATG.
Also, I'm using the module sys, to import DictReader and also reader
You can always try to create the function on your own.
You can use my code here:
def csv_to_dict(csv_file):
key_list = [key for key in csv_file[:csv_file.index('\n')].split(',')] # save the keys
data = {} # every dictionary
info = [] # list of dicitionaries
# for each line
for line in csv_file[csv_file.index('\n') + 1:].split('\n'):
count = 0 # this variable saves the key index in my key_list.
# for each string before comma
for value in line.split(','):
data[key_list[count]] = value # for each key in key_list (which I've created before), I put the value. This is the way to set a dictionary values.
count += 1
info.append(data) # after updating my data (dictionary), I append it to my list.
data = {} # I set the data dictionary to empty dictionary.
print(info) # I print it.
### Be aware that this function prints a list of dictionaries.
I want to store values that I plan to later use for sorting pdfs on my computer using PyPDF2.
I thought that if I created a class and stored identifying info for each type of file (such as a descriptor, a string that is unique to the file and can be found by PyPDF2 later such as an account number, and the path where the file should be moved to) that would work. Something like this:
class File_Sort(object):
def __init__(self, identifier, file_text, file_path):
self.identifier = identifier
self.file_text = file_text
self.file_path = file_path
so an example input from me would be:
filetype0001 = File_Sort("Phone Bill", "123456", "/Users/Me/PhoneBills/")
I would like to be able to have users generate new file types via a series of raw_input questions, but I can't figure how to generate the variable to create a new instance, so that I can get:
filetype000[automatically incrementing number] = File_Sort(UserResponse1, UserResponse3, UserResponse3).
Creating the "filetype000[automatically incrementing number]" text itself seems easy enough with:
file_number += 1
file_name = "filetype" + str(file_number).zfill(4)
but how do you turn the generated file_name string into a variable and populate it?
It sounds like you're wanting to dynamically create variables. That's almost always a foolish thing to do. Instead, you should be using a data structure like a list or dictionary, indexed by the parts of the variable name you wanted to generate dynamically.
So instead of creating a list named filetype000, start with a list named filetypes, and append an inner list, so you can do filetypes[0] to get at it. Or if string names make more sense for your specific application, let filetypes be a dictionary, and access the inner lists with something like filetypes['pdf'].
I'm being a little vague here because I don't really understand all of your pseudocode. It's not at all obvious what the purpose of the [automatically incrementing number] parts of your example are, so I'm more or less ignoring those bits. You probably just want to start with an empty list and append values to it, rather than somehow initializing it to a specific size and magically indexing it.
so fyi this is what I ended up using:
file_descriptor = []
file_string = []
file_location = []
filetype_new = len(file_descriptor)
input_descriptor = raw_input("What is the description of the new file type? ")
file_descriptor.append(input_descriptor)
input_filestring = raw_input("What is unique string to search for in this file type? ")
file_string.append(input_filestring)
input_filelocation = raw_input("where should we put this file type? ")
file_location.append(input_filelocation)
print("file%s: %s, \t%s, \t%s" % (str(filetype_new+1).zfill(4), file_descriptor[filetype_new], file_string[filetype_new], file_location[filetype_new]))
review = raw_input("\nWould you like to review the current files? y/n ").lower()
while review not in "yn":
review = raw_input("Sorry, I don't understand. Would you like to review your file types? y/n ").lower()
print("There are currently sort instructions for %s filetypes: " % (len(file_descriptor)))
file_increment = 0
while file_increment in range(0, len(file_descriptor)):
print("file%s: %s, \t%s, \t%s" % (
str(file_increment + 1).zfill(4), file_descriptor[file_increment], file_string[file_increment],
file_location[file_increment]))
file_increment += 1
thanks for your advice.
I’m having a problem with a dictionary. I"m using Python3. I’m sure there’s something easy that I’m just not seeing.
I’m reading lines from a file to create a dictionary. The first 3 characters of each line are used as keys (they are unique). From there, I create a list from the information in the rest of the line. Each 4 characters make up a member of the list. Once I’ve created the list, I write to the directory with the list being the value and the first three characters of the line being the key.
The problem is, each time I add a new key:value pair to the dictionary, it seems to overlay (or update) the values in the previously written dictionary entries. The keys are fine, just the values are changed. So, in the end, all of the keys have a value equivalent to the list made from the last line in the file.
I hope this is clear. Any thoughts would be greatly appreciated.
A snippet of the code is below
formatDict = dict()
sectionList = list()
for usableLine in formatFileHandle:
lineLen = len(usableLine)
section = usableLine[:3]
x = 3
sectionList.clear()
while x < lineLen:
sectionList.append(usableLine[x:x+4])
x += 4
formatDict[section] = sectionList
for k, v in formatDict.items():
print ("for key= ", k, "value =", v)
formatFileHandle.close()
You always clear, then append and then insert the same sectionList, that's why it always overwrites the entries - because you told the program it should.
Always remember: In Python assignment never makes a copy!
Simple fix
Just insert a copy:
formatDict[section] = sectionList.copy() # changed here
Instead of inserting a reference:
formatDict[section] = sectionList
Complicated fix
There are lots of things going on and you could make it "better" by using functions for subtasks like the grouping, also files should be opened with with so that the file is closed automatically even if an exception occurs and while loops where the end is known should be avoided.
Personally I would use code like this:
def groups(seq, width):
"""Group a sequence (seq) into width-sized blocks. The last block may be shorter."""
length = len(seq)
for i in range(0, length, width): # range supports a step argument!
yield seq[i:i+width]
# Printing the dictionary could be useful in other places as well -> so
# I also created a function for this.
def print_dict_line_by_line(dct):
"""Print dictionary where each key-value pair is on one line."""
for key, value in dct.items():
print("for key =", key, "value =", value)
def mytask(filename):
formatDict = {}
with open(filename) as formatFileHandle:
# I don't "strip" each line (remove leading and trailing whitespaces/newlines)
# but if you need that you could also use:
# for usableLine in (line.strip() for line in formatFileHandle):
# instead.
for usableLine in formatFileHandle:
section = usableLine[:3]
sectionList = list(groups(usableLine[3:]))
formatDict[section] = sectionList
# upon exiting the "with" scope the file is closed automatically!
print_dict_line_by_line(formatDict)
if __name__ == '__main__':
mytask('insert your filename here')
You could simplify your code here by using a with statement to auto close the file and chunk the remainder of the line into groups of four, avoiding the re-use of a single list.
from itertools import islice
with open('somefile') as fin:
stripped = (line.strip() for line in fin)
format_dict = {
line[:3]: list(iter(lambda it=iter(line[3:]): ''.join(islice(it, 4)), ''))
for line in stripped
}
for key, value in format_dict.items():
print('key=', key, 'value=', value)
I am trying to write a routine to read values from a text file, (names and scores) and then be able to sort the values az by name, highest to lowest etc. I am able to sort the data but only by the position in the string, which is no good where names are different lengths. This is the code I have written so far:
ClassChoice = input("Please choose a class to analyse Class 1 = 1, Class 2 = 2")
if ClassChoice == "1":
Classfile = open("Class1.txt",'r')
else:
Classfile = open("Class2.txt",'r')
ClassList = [line.strip() for line in Classfile]
ClassList.sort(key=lambda s: s[x])
print(ClassList)
This is an example of one of the data files (Each piece of data is on a separate line):
Bob,8,7,5
Fred,10,9,9
Jane,7,8,9
Anne,6,4,8
Maddy,8,5,5
Jim, 4,6,5
Mike,3,6,5
Jess,8,8,6
Dave,4,3,8
Ed,3,3,4
I can sort on the name, but not on score 1, 2 or 3. Something obvious probably but I have not been able to find an example that works in the same way.
Thanks
How about something like this?
indexToSortOn = 0 # will sort on the first integer value of each line
classChoice = ""
while not classChoice.isdigit():
classChoice = raw_input("Please choose a class to analyse (Class 1 = 1, Class 2 = 2) ")
classFile = "Class%s.txt" % classChoice
with open(classFile, 'r') as fileObj:
classList = [line.strip() for line in fileObj]
classList.sort(key=lambda s: int(s.split(",")[indexToSortOn+1]))
print(classList)
The key is to specify in the key function that you pass in what part of each string (the line) you want to be sorting on:
classList.sort(key=lambda s: int(s.split(",")[indexToSortOn+1]))
The cast to an integer is important as it ensures the sort is numeric instead of alphanumeric (e.g. 100 > 2, but "100" < "2")
I think I understand what you are asking. I am not a sort expert, but here goes:
Assuming you would like the ability to sort the lines by either the name, the first int, second int or third int, you have to realize that when you are creating the list, you aren't creating a two dimensional list, but a list of strings. Due to this, you may wish to consider changing your lambda to something more like this:
ClassList.sort(key=lambda s: str(s).split(',')[x])
This assumes that the x is defined as one of the fields in the line with possible values 0-3.
The one issue I see with this is that list.sort() may sort Fred's score of 10 as being less than 2 but greater than 0 (I seem to remember this being how sort worked on ints, but I might be mistaken).
I'm a Python newbie trying to parse a file to make a table of memory allocations. My input file is in the following format:
48 bytes allocated at 0x8bb970a0
24 bytes allocated at 0x8bb950c0
48 bytes allocated at 0x958bd0e0
48 bytes allocated at 0x8bb9b060
96 bytes allocated at 0x8bb9afe0
24 bytes allocated at 0x8bb9af60
My first objective is to make a table that counts the instances of a particular number of byte allocations. In other words, my desired output for the above input would be something like:
48 bytes -> 3 times
96 bytes -> 1 times
24 bytes -> 2 times
(for now, I'm not concerned about the memory addresses)
Since I'm using Python, I thought doing this using a dictionary would be the right way to go (based on about 3 hours' worth of reading Python tutorials). Is that a good idea?
In trying to do this using a dictionary, I decided to make the number of bytes the 'key', and a counter as the 'value'. My plan was to increment the counter on every occurrence of the key. As of now, my code snippet is as follows:
# Create an empty dictionary
allocationList = {}
# Open file for reading
with open("allocFile.txt") as fp:
for line in fp:
# Split the line into a list (using space as delimiter)
lineList = line.split(" ")
# Extract the number of bytes
numBytes = lineList[0];
# Store in a dictionary
if allocationList.has_key('numBytes')
currentCount = allocationList['numBytes']
currentCount += 1
allocationList['numBytes'] = currentCount
else
allocationList['numBytes'] = 1
for bytes, count in allocationList.iteritems()
print bytes, "bytes -> ", count, " times"
With this, I get a syntax error in the 'has_key' call, which leads me to question whether it is even possible to use variables as dictionary keys. All examples I have seen so far assume that keys are available upfront. In my case, I can get my keys only when I'm parsing the input file.
(Note that my input file can run into thousands of lines, with hundreds of different keys)
Thank you for any help you can provide.
Learning a language is as much about the syntax and basic types as it is about the standard library. Python already has a class that makes your task very easy: collections.Counter.
from collections import Counter
with open("allocFile.txt") as fp:
counter = Counter(line.split()[0] for line in fp)
for bytes, count in counter.most_common():
print bytes, "bytes -> ", count, " times"
You get a syntax error because you are missing the colon at the end of this line:
if allocationList.has_key('numBytes')
^
Your approach is fine, but it might be easier to use dict.get() with a default value:
allocationList[numBytes] = allocationList.get(numBytes, 0) + 1
Since your allocationList is a dictionary and not a list, you might want to chose a different name for the variable.
The dict.has_key() method of dictionnary has disappeared in python3, to replace it, use the in keyword :
if numBytes in allocationList: # do not use numBytes as a string, use the variable directly
#do the stuff
But in your case, you can also replace all the
if allocationList.has_key('numBytes')
currentCount = allocationList['numBytes']
currentCount += 1
allocationList['numBytes'] = currentCount
else
allocationList['numBytes'] = 1
with one line with get:
allocationList[numBytes] = allocationList.get(numBytes, 0) + 1
You most definitely can use variables as dict keys. However, you have a variable called numBytes, but are using a string containing the text "numBytes" - you're using a string constant, not the variable. That won't cause the error, but is a problem. Instead, try:
if numBytes in allocationList:
# do stuff
Additionally, consider a Counter. This is a convenient class for handling the case you're looking at.