Registration function isn't working because of problem connected to csv file - python

The main problem is that after inputting a login program just returns me back instead of working with row in my sorted dictionary. I have a function, that created for registration, Previously I worked with it because I have the full program with autorization and registration. Now I need this function again for another program with autorization, but it doesn't working (but it worked...)
here is my function:
def reg(r) -> None:
loginnn = input_str("Create login:\n", "login must be made of 4 - 20 symbols")
with open("hashpy.csv") as f:
reader = csv.DictReader(f, delimiter=',')
sorted_dict = sorted(reader, key=lambda k: k['login'])
for row in sorted_dict:
#don't worry about code below, it's still under 'construction'
login, password, salt, role = row:
passworddd = input_str("Create password:\n", "password must be made of 4 - 20 symbols")
salt = uuid.uuid4().hex
print(salt + "salt")
passworddd = hashlib.sha256(password.encode() + salt.encode())
print(passworddd)
print("Registraion is succeed!")
with open(file_name2, 'a') as f:
f.write(f"\n{loginnn},{passworddd},{salt},{r}") # r == role (r is an argument)
return
I used debugger and I saw, that everything is good till program compiling this line:
sorted_dict = sorted(reader, key=lambda k: k['login']) which returns me sorted_dict []
After this line program just returns to
with open("hashpy.csv") as f: with 0 changes
and then returns me back to menu.

Related

Python: Decrypting a file (have key)

I encrypted a file from ascii randomized key. I need to decrypt back into normal letters from and then put that into a new file
import random
lst = list(range(1,128)) #for key
numbersran = list()
while len(numbersran) < 128:
candidate = random.randint(1,128)
if candidate not in numbersran:
numbersran.append(candidate)
listsdict = dict(zip(lst,numbersran)) #makes key, changes every time
print("Encytption key=", listsdict)
print()
filename=input("Enter File: ")
with open(filename, "r") as file:
filetxt = file.read()
ascii_codes = [ord(c) for c in filetxt]
encrypted_codes = [listsdict[code] for code in ascii_codes]
print('\nEncrypted file: ',encrypted_codes)
cypher = "".join([chr(c) for c in encrypted_codes]) #encrypts from key
#decrypt below here into a file using the key to translate (should be original text from file)
I am not too sure how to reverse the process back to the original text in file. Must be decrypted back, can't just be copied from og file
The decryption process should be reverse of what has been done for encryption. Find below the code snippet.
decrypted_file = [ord(c) for c in cypher]
decrypted_key = list()
for value in decrypted_file:
for key in listsdict:
if listsdict[key] == value:
decrypted_key.append(key)
break
print(''.join([chr(c) for c in decrypted_key]))
There can be better ways to achieve the decryption but the solution in its naivest form should be like above.
easy way to replace this code snippet:
for value in decrypted_file:
for key in listsdict:
if listsdict[key] == value:
decrypted_key.append(key)
break
is to reverse listsdict keys with value as suggested by #scott hunter
decrypted_file = [ord(c) for c in cypher]
decrypted_key = list()
listsdict = dict(zip(numbersran,lst))
decrypted_key = [listsdict[code] for code in decrypted_file]
print(''.join([chr(c) for c in decrypted_key]))

How to remove an element from a JSON array using Python?

I'm currently trying to make a Chromebook rental application for my high school that stores checkout information in a JSON file. Everything works except removing data from the JSON array. I found a YouTube video(link) that I thought would work as a solution, so I followed along with that. However, whenever there's more than two elements and I enter anything higher than two, it doesn't delete anything. Even worse, when I enter the number one, it deletes everything but the zero index(whenever the array has more than two elements in it).
Here's the Python code:
def view_data(): # Prints JSON Array to screen
with open(filename, "r") as f:
data = json.load(f)
i = 0
for item in data:
name = item["name"]
chromebook = item["chromebook"]
check_out = item["time&date"]
print(f"Index Number: {i}")
print(f"Name : {name}")
print(f"Chromebook : {chromebook}")
print(f"Time Of Checkout: {check_out} ")
print("\n\n")
i = i + 1
def delete_data(): # Deletes an element from the array
view_data()
new_data = []
with open(filename, "r") as f:
data = json.load(f)
data_length = len(data) - 1
print("Which index number would you like to delete?")
delete_option = input(f"Select a number 0-{data_length}: ")
i = 0
for entry in data:
if i == int(delete_option):
pass
i = + 1
else:
new_data.append(entry)
i = + 1
with open(filename, "w") as f:
json.dump(new_data, f, indent=4)
Here's the JSON file code:
[
{
"name": "Tyler",
"chromebook": "12123223",
"time&date": "Check Out Time: 13:33:22 May-11-2021"
},
{
"name": "Craig",
"chromebook": "41222224",
"time&date": "Check Out Time: 13:33:34 May-11-2021"
},
{
"name": "Bill",
"chromebook": "3235223",
"time&date": "Check Out Time: 13:33:46 May-11-2021"
}
]
For example, say the user wanted to remove the second index in the JSON array. Is there a better way to implement that in my Python script?
I'm still a fairly new and learning Python developer, and if there's any better solution I'm open to suggestions. If you need for info, I'll be active.
First question
However, whenever there's more than two elements and I enter anything higher than two, it doesn't delete anything. Even worse, when I enter the number one, it deletes everything but the zero index(whenever the array has more than two elements in it).
Inside delete_data() you have two lines reading i = + 1, which just assignes +1 (i.e., 1) to i. Thus, you're never increasing your index. You probably meant to write either i = i+1 or i += 1.
def delete_data(): # Deletes an element from the array
view_data()
new_data = []
with open(filename, "r") as f:
data = json.load(f)
data_length = len(data) - 1
print("Which index number would you like to delete?")
delete_option = input(f"Select a number 0-{data_length}: ")
i = 0
for entry in data:
if i == int(delete_option):
i += 1 # <-- here
else:
new_data.append(entry)
i += 1 # <-- and here
with open(filename, "w") as f:
json.dump(new_data, f, indent=4)
Second question: further improvements
Is there a better way to implement that in my Python script?
First, you can get rid of manually increasing i by using the builtin enumerate generator. Second, you could make your functions reusable by giving them parameters - where does the filename in your code example come from?
# view_data() should probably receive `filename` as a parameter
def view_data(filename: str): # Prints JSON Array to screen
with open(filename, "r") as f:
data = json.load(f)
# iterate over i and data simultaneously
# alternatively, you could just remove i
for i, item in enumerate(data):
name = item["name"]
chromebook = item["chromebook"]
check_out = item["time&date"]
print(f"Index Number: {i}")
print(f"Name : {name}")
print(f"Chromebook : {chromebook}")
print(f"Time Of Checkout: {check_out} ")
print("\n\n")
# not needed anymore: i = i + 1
# view_data() should probably receive `filename` as a parameter
def delete_data(filename: str): # Deletes an element from the array
view_data()
new_data = []
with open(filename, "r") as f:
data = json.load(f)
data_length = len(data) - 1
print("Which index number would you like to delete?")
delete_option = input(f"Select a number 0-{data_length}: ")
# iterate over i and data simultaneously
for i, entry in enumerate(data):
if i != int(delete_option):
new_data.append(entry)
with open(filename, "w") as f:
json.dump(new_data, f, indent=4)
Furthermore, you could replace that for-loop by a list comprehension, which some may deem more "pythonic":
new_data = [entry for i, entry in enumerate(data) if i != int(delete_option)]
There are easier ways to delete an element by index from a Python list.
Given li = ["a", "b", "c"], you can delete element 1 ("b") by index in (at least) the following ways:
li.pop(1) # pop takes an index (defaults to last) and removes and returns the element at that index
del li[1] # the del keyword will also remove an element from a list
So, here's some updated code:
def view_data(): # Prints JSON Array to screen
with open(filename, "r") as f:
data = json.load(f)
i = 0
for item in data:
name = item["name"]
chromebook = item["chromebook"]
check_out = item["time&date"]
print(f"Index Number: {i}")
print(f"Name : {name}")
print(f"Chromebook : {chromebook}")
print(f"Time Of Checkout: {check_out} ")
print("\n\n")
i = i + 1
def delete_data(): # Deletes an element from the array
view_data()
with open(filename, "r") as f:
data = json.load(f)
data_length = len(data) - 1
print("Which index number would you like to delete?")
delete_option = input(f"Select a number 0-{data_length}: ")
del data[int(delete_option)] # or data.pop(int(delete_option))
with open(filename, "w") as f:
json.dump(data, f, indent=4)
import json
data = json.loads(jsonString) #convert json string to object
delete_option = input(f"Select a number 0-{data_length}: ")
del data[int(delete_option)]

Python and Comparing File Changes

d = feedparser.parse('somerssfeed/rss.xml')
message = {}
smessage = {}
for post in d.entries:
message[post.link] = post.title
fwrite = open("db.txt", "a")
for k, v in message.items():
if k in open("db.txt", "r"):
print("already exists")
else:
fwrite.write("\n" + "{0}".format(k) + "\n")
smessage[k] = v
What i want to achieve is parsing RSS feeds and write their links in to a text file. But the problem is when i run the script next time it should't return old rss items so i compare them via text file except it's failing. On the first run it writes all links, second run it should return empty because all of links are the same but it writes again the same links
EDIT:
after a whole day of trial and error this worked:
for k, v in message.items():
if k in open('db.txt').read():
print('already exists')
else:
smessage[k] = v
fwrite = open("db.txt", "a")
fwrite.write('\n{0}\n'.format(k))
fwrite.close()
You aren't using the correct syntax to open the file. Use this :
g = open("db.txt","r")
lines = xml_file.readlines()
if k in lines:
print ("already exists");

self modifying python script

I want to create python script which can modify code in that script itself using Python Language Services or using any other way.
e.g. A script which keep track of its count of successfull execution
import re
COUNT = 0
def updateCount():
# code to update second line e.g. COUNT = 0
pass
if __name__ == '__main__':
print('This script has run {} times'.format(COUNT))
updateCount()
On successful execution of this script code should get changed to
import re
COUNT = 1
def updateCount():
# code to update second line e.g. COUNT = 0
pass
if __name__ == '__main__':
print('This script has run {} times'.format(COUNT))
updateCount()
Simple approach came to my mind was to open __file__ in write mode and do requried modification using reguler expessions etc. But that did not work I got exception io.UnsupportedOperation: not readable. Even if this approach would be working then it would be very risky because it can spoil my whole script. so I am looking for solution using Python Language Services.
Yes, you can use the language services to achieve self-modification, as in following example:
>>> def foo(): print("original foo")
>>> foo()
original foo
>>> rewrite_txt="def foo(): print('I am new foo')"
>>> newcode=compile(rewrite_text,"",'exec')
>>> eval(newcode)
>>> foo()
I am new foo
So, by new dynamically generated code you can replace stuff contained in the original source file, without modifying the file itself.
A python script is nothing more than a text file. So, you are able to open it as an external file and read & write on that. (Using __file__ variable you can get the exact name of your script):
def updateCount():
fin = open(__file__, 'r')
code = fin.read()
fin.close()
second_line = code.split('\n')[1]
second_line_parts = second_line.split(' ')
second_line_parts[2] = str(int(second_line_parts[2])+1)
second_line = ' '.join(second_line_parts)
lines = code.split('\n')
lines[1] = second_line
code = '\n'.join(lines)
fout = open(__file__, 'w')
fout.write(code)
fout.close()
#kyriakosSt's answer works but hard-codes that the assignment to COUNT must be on the second line, which can be prone to unexpected behaviors over time when the line number changes due to the source being modified for something else.
For a more robust solution, you can use lib2to3 to parse and update the source code instead, by subclassing lib2to3.refactor.RefactoringTool to refactor the code using a fixer that is a subclass of lib2to3.fixer_base.BaseFix with a pattern that looks for an expression statement with the pattern 'COUNT' '=' any, and a transform method that updates the last child node by incrementing its integer value:
from lib2to3 import fixer_base, refactor
COUNT = 0 # this should be incremented every time the script runs
class IncrementCount(fixer_base.BaseFix):
PATTERN = "expr_stmt< 'COUNT' '=' any >"
def transform(self, node, results):
node.children[-1].value = str(int(node.children[-1].value) + 1)
return node
class Refactor(refactor.RefactoringTool):
def __init__(self, fixers):
self._fixers = [cls(None, None) for cls in fixers]
super().__init__(None)
def get_fixers(self):
return self._fixers, []
with open(__file__, 'r+') as file:
source = str(Refactor([IncrementCount]).refactor_string(file.read(), ''))
file.seek(0)
file.write(source)
Demo: https://repl.it/#blhsing/MushyStrangeClosedsource
This will edit the module level variables defined before _local_config. Later, process an update to the dictionary, then replace the line when iterating over the source file with the new _local_config values:
count = 0
a = 0
b = 1
c = 1
_local_config = dict(
filter(
lambda elem: (elem[0][:2] != "__") and (str(elem[1])[:1] != "<"),
globals().items(),
),
)
# do some stuff
count += 1
c = a + b
a = b
b = c
# update with new values
_local_config = dict(
filter(
lambda elem: elem[0] in _local_config.keys(),
globals().items(),
)
)
# read self
with open(__file__, "r") as f:
new_file = ""
for line in f.read().split("\n"):
for k, v in _local_config.items():
search = f"{k} = "
if search == line[: len(k) + 3]:
line = search + str(v)
_local_config.pop(k)
break
new_file += line + "\n"
# write self
with open(__file__, "w") as f:
f.write(new_file[:-1])

Python- Saving Results to a File and Recalling Them

I'm writing a program in Python that will store Student IDs, names, and D.O.B.s.
The program gives the user the ability to remove, add, or find a student. Here is the code:
students={}
def add_student():
#Lastname, Firstname
name=raw_input("Enter Student's Name")
#ID Number
idnum=raw_input("Enter Student's ID Number")
#D.O.B.
bday=raw_input("Enter Student's Date of Birth")
students[idnum]={'name':name, 'bday':bday}
def delete_student():
idnum=raw_input("delete which student:")
del students[idnum]
def find_student():
print "Find"
menu = {}
menu['1']="Add Student."
menu['2']="Delete Student."
menu['3']="Find Student"
menu['4']="Exit"
while True:
options=menu.keys()
options.sort()
for entry in options:
print entry, menu[entry]
selection=raw_input("Please Select:")
if selection =='1':
add_student()
elif selection == '2':
delete_student()
elif selection == '3':
find_students
elif selection == '4':
break
else:
print "Unknown Option Selected!"
The problem I am having is I cannot figure out how to have the program save any added records to a file when the program ends. It also would need to read back the records when the program restarts.
I keep trying to find tutorials for this sort of thing online, but to no avail. Is this the sort of code I'd want to add?:
f = open("myfile.txt", "a")
I'm new to Python so any help would be appreciated. Thanks so much.
It depends, if you want to actually save python objects, check out Pickle or Shelve, but if you just want to output to a text file, then do the following:
with open('nameOfYourSaveFile', 'w') as saveFile:
#.write() does not automatically add a newline, like print does
saveFile.write(myString + "\n")
Here's an answer that explains the different arguments to open, as in w, w+, a, etc.
As an example, say we have:
with open('nameOfYourSaveFile', 'w') as saveFile:
for i in xrange(10):
saveFile.write(name[i] + str(phoneNumber[i]) + email[i] + "\n")
To read the file back, we do:
names = []
numbers = []
emails = []
with open('nameOfYourSaveFile', 'r') as inFile:
for line in inFile:
#get rid of EOL
line = line.rstrip()
#random example
names.append(line[0])
numbers.append(line[1])
emails.append(line[2])
#Or another approach if we want to simply print each token on a newline
for word in line:
print word
import pickle,os
if os.path.exists("database.dat"):
students = pickle.load(open("database.dat"))
else:
students = {}
... #your program
def save():
pickle.dump(students,open("database.dat","w"))

Categories