Password protected zip file wont output correctly? - python

I am using Python to create a list of groups. It only makes sense to me that, using the code, I have for creating the password protected zip, I can create the input in my code as long as it is created before listing the input. As such, I have created a txt file which then needs to be placed in a password protected zip. With the code I am using below, I get this error message when I try to run it: (OSError: error in opening /Users/name/Desktop/Groups.txt for reading). I'm simply not very experienced in this regard and wouldn't know how to solve this issue (+ I am extremely desperate right now). This is the code I have so far, but it does not work:
#creates .txt file to put in zip folder
with open("Groups.txt", 'w') as file:
file.write("Each row is a group:" + '\n')
for row in final_group:
s = ", ".join(map(str, row))
file.write(s+'\n')
# creates password protected zip
inpt = "/Users/name/Desktop/Groups.txt"
pre = None
oupt = "/Users/name/Desktop/Groups.zip"
password = "password"
com_lvl = 5
pyminizip.compress(inpt, None, oupt, password, com_lvl)
Could someone help me out here?

The input file might be in a different directory, because of which there's an error. You can either
Set inpt = "Groups.txt"
Set with open("/Users/name/Desktop/Groups.txt", 'w') as file:

Related

how to change boolean value thats another file

Im trying to make a thing that can detect whether or not a user wants their password stored for next time they run the program, The reason im using a boolean for this is so in the files that need to use the password they can check to see if storepass is True then get the pass/user from a .env if not they can get the password from the storepasswordquestion file amd use that and it wont get stored when the user closes the program.
I have a file called booleans that im using to store booleans, in it is this:
storepass = False
In a other file called storepasswordquestion i have:
import booleans
username = 'username'
password = 'password'
question = input('Would you like your password to be stored for use next time?') # enter y
if question == 'y':
booleans.storepass = True
# store password/username in .env
As i understand it import booleans loads the booleans file, Then i think booleans.storepass is like a variable but like a copy of the one in booleans? Because when i go on the booleans file again its still False.
Im needing to change storepass to True in the booleans file and then save it.
Then i think booleans.storepass is like a variable but like a copy of the one in booleans? Because when i go on the booleans file again its still False.
That's correct - you can't change the values inside a .py file just by importing and then setting within another. py file. The standard way to manipulate files is by using some variation of
with open('boolean.py', 'w') as f:
f.write('storepass = False')
Personally, I really dislike writing over .py files like this; I usually save as JSON. So "boolean.json" can have just
{"storepass": false}
and then in your python code you can (instead of importing) get it as
# import json
boolean = json.load(open('boolean.json', 'r'))
and set storepass with
# import json
boolean.storepass = True
with open('boolean.json', 'w') as f:
json.dump(boolean, f, indent=4)
## NOT f.write(boolean)
and this way, if there are more values in boolean, they'll also be preserved (as long as you don't use the variable for anything else in between...)
You're expecting changing a variable's value to change source code. Luckily, that's not how this works!
You need to make a mental distinction between the source code that the python interpreter reads, and the values of variables.
What you need is indeed, as you say,
Im needing to change storepass to True in the booleans file and then save it.
So, you would need to open that boooleans.py as a text file, not as a python program, read and interpret it as pairs of keys and values, modify the right one (so, storepass in this case), write the result back to the file. Then, the next time someone imports it, they would see the different setting.
This is a bad approach you've chosen:
Reading and parsing python files is very hard in general, because, well, Python is a programming language and can do much more than just store settings
The change only takes effect the next time the program is run and the settings are imported anew. This has no effect on other parts of an already running program. So, that's bad.
Things get a lot easier if you do two things:
Get rid of the idea to store settings in a Python source code file. Instead, use one of the multiple ways that python has to read structured data from a file. For your use case, usage of the configparser module might be easiest – a ConfigParser has a read and a write method, with which you can, you guessed it, read and write your config file. There's multiple other modules that Python brings that can do similar things. The json module, for example, is a sensible way to store especially logically hierarchically structured settings. And of course, the place where you store passwords might also be a place where you could store settings – depending on what that is.
The approach of having a single module that you import (your booleans) is a good one, as it ensures that there's a single booleans that is the "source of truth" about these settings. I propose you put the configuration loading into such a single module:
# this is settings.py
import json
SETTINGSFILE = "settings.json"
# when this is loaded the first time, load things from the settings file
try:
with open(SETTINGSFILE) as sfile:
_settings = json.load(sfile)
except FileNotFoundError:
# no settings file yet. We'll just have empty settings
# Saving these will create a file
_settings = {}
def __getattr__(settingname):
try:
return _settings[settingname]
except KeyError as e:
# you could implement "default settings" by checking
# in a default settings dictionary that you create above
# but here, we simply say: nay, that setting doesn't yet
# exist. Which is as good as your code would have done!
raise AttributeError(*e.args) from e
def save():
with open(SETTINGSFILE, "w") as sfile:
json.dump(_settings, sfile)
def update_setting(settingname, value):
_settings[settingname] = value
save()
which you can then use like this:
import settings
…
if settings.storepass:
"Do what you want here"
…
# User said they want to change the setting:
should_we_store = (input("should we store the password? ").upper == "Y")
# this updates the setting, i.e. it's instantly visible
# in other parts of the program, and also stores the changed config
# to the settings.json file
settings.update_setting("storepass", should_we_store)
You are changing the value inside the runtime, meaning you can actually change it. Meaning if you are ever trying to print out the value inside the if condition like this:
booleans.storepass = True
print(booleans.storepass)#This should return True
But your problem is that you are not actually changing the file. In order to change the file you should do it like this( This is the general way to write to a file with python from my research it should work in your case as well.
f = open("booleans.py", "w")
f.write("booleans.storepass = True")
f.close()
In short what you are doing is actually true for runtime, but if you want to store the result in a file this is the way to do it.

Writing to a list in an external module

So I'm working on a discord bot that has commands like meme commands, roast commands, etc, and since I'm still learning python I haven't started to work with databases yet and store all the roasts in a separate py file and then import it as a module in the bot file.
I want to create another .py file that imports the list and appends to it instead of me opening the py file and edit it myself... heres the code i've written for now and even though it executes without any errors, the list module does not append.
from roasts_list import roast
adder_value = input("What would you like to add? \n")
roast.append(adder_value)
the module is the roasts_list and the list name is roast.
Any solutions?
Rather than creating an external python module for storing the list, you can store it in a text file.
adder_value = input("What would you like to add? \n")
#add roasts to the text file
roast_file = open("roast.txt", "a")
roast_file.write(adder_value + "\n") #adds roast to the text file
roast_file.close()
#get roasts
roast_file = open("roast.txt", "r")
roast_list = roast_file.read().splitlines() #returns a list of all roasts in the text file
roast_file.close()
Using this method, you can save your roasts in text files, and use them accordingly.
Agreeing with Devansh. If you go with your approach to save them in e.g. a list variable from a .py file, that would mean that all of your values would only be stored in memory and as soon as the program stops, all values will be lost. If you want to persistently store the values, the easiest way would be to store them in a file.
In addition to Devansh approach above, i would suggest opening the file with its context manager, and adding a try/except to handle if you try getting roasts from the file before it's created, making it a little bit more stable in a running program.
#add roasts to the text file
def add_roast():
adder_value = input("What would you like to add? ")
with open("roast.txt", "a") as roast_file:
roast_file.write(adder_value + "\n") #adds roast to the text file
#get roasts
def get_roasts():
try:
with open("roast.txt", "r") as roast_file:
return roast_file.read().splitlines()
except FileNotFoundError as e:
print("No roasts exist yet")
add_roast()
print(get_roasts())

How do I create a temporary ZIP in Python 3.x using pyminizip?

I need to create a temporary zip file to store files. That ZIP file needs to be encrypted, so zipfile won't do the trick here. The file will be further encrypted (the ZIP will be encrypted again into another file), so zipping the file is used as a way of reducing its size for faster internet transmission as well as the first layer of encryption.
Here's what I've got so far:
import getpass
import tempfile
import pyminizip
def ZipFunction():
#This zips the file and encrypts it with a password
filename = input('Enter the file name: ')
passkey = getpass.getpass(prompt='Enter the password for the file: ')
passkey2 = getpass.getpass(prompt='Confirm the password: ')
if passkey != passkey2:
print('The passwords must be the same! Please restart the process.')
exit()
else:
#Here's where I need help
with tempfile.TemporaryFile() as tmp:
with pyminizip.compress(filename,None,tmp,passkey,9) as archive:
zipstring = archive.readlines()
#From here on the zipstring var is encrypted and creates the "further encrypted"
#file. From here on the script works normally
The error returned is ValueError: expected arguments are compress(src, srcpath, dst, pass, level).
I'd be willing to change pyminizip to another tool that can create encrypted zip files. This "dual encryption layer" is a customer demand, and although I don't really think it's necessary, I don't have the authority to scrap it from the project.
I'm not used to dealing with Temporary Files. What am I doing wrong here?
With the tempfile-module temporary files can be created which are automatically deleted when closing or leaving a with-block. With the pyminizip-module encrypted zip-files can be obtained.
pyminizip.compress expects as third parameter the path where the generated zip-file should be saved. If a file is already there, an attempt is made to overwrite it. The current code uses the reference to the tempfile (tmp), which leads to the observed error message:
ValueError: expected arguments are compress(src, srcpath, dst, pass, level)
The direct cause of the error is that the reference itself and not its file name is used, i.e. to avoid the error, tmp.name should actually be used instead of tmp. However, if this is changed, a different error message is generated, namely
OSError: error in closing <path to temo file> (-102)
This is because the pyminizip-module tries to delete the tempfile while it is still open. If the tempfile were closed before, it would be overwritten without error message. However, this would only create a normal file and not a tempfile, i.e. the file wouldn't be deleted automatically when closing or leaving the with-block.
Thus, it is not possible to create temporary, encrypted zip-files with the tempfile- and pyminizip-module in this way. However, the tempfile-module allows the creation of temporary files as well as temporary directories. Like temporary files, temporary directories are deleted when leaving a with-block. If a temporary directory is deleted, the files contained therein are also deleted. Therefore an alternative would be common, encrypted zip-files (created with the pyminizip-module), which are stored in a temporary folder (created with the tempfile-module):
...
with tempfile.TemporaryDirectory() as tdir:
sourceFile = <path to file to be zipped>
destinationFile = "destFile.zip"
password = "whatever"
compression_level = 9 # 1-9
pyminizip.compress(sourceFile, None, tdir + "\\" + destinationFile, password, compression_level)
# inside with-block: temp-directory and contained encrypted zip-files exist
...
# outside with-block: temp-directory and contained encrypted zip-files deleted
...
If the with-block is left, the temporary directory is deleted along with any encrypted zip files it contains.
By the way: pyminizip.compress doesn't support a with-statement. This would cause the error message: AttributeError: __enter__. In the current code you can't see this error message, because the posted error message is triggered before.

Editing Paths in Python

I'm trying to create a program that duplicates itself to another location and creates a batch file on the desktop. I can make it duplicate itself and I can create the batch file but I need some help with the paths.
I can find the path that my program is currently in. Both the direct path and the path to the directory. My problem lies in the fact that I want to place the file in (let's just say for simplicity) 'C:\Users\Me\Documents'. How would I edit the path? I want to be able to place this on a generic windows computer so I can't hard code the path in because each user will be different. This goes the same for placing the batch file and setting it for the right directory to run the python script in documents.
I have tried both
import os
print os.path.dirname(os.path.abspath(__file__))
and
import os
print os.path.abspath(__file__)
but am clueless as to how to edit the path. When I try googling for it and searching this wonderful site, all I get is stuff about configuring the Python path on windows and other stuff that I can't quite understand at my current level of Python.
Now I turn to you, can you help? Any input would be appreciated, if you could explain how it worked that would be even better!
<>
Due to some questions about my code (and a specific one to post it) Here it is
from sys import argv # Imports module
import os
script, create = argv # Gets script name and desired amount of copies
data = open(script) # Creates a variable to store the script
indata = copy.read() # Creates the data to be copied from the script
batData = """
echo off
%s
""" % # This is not finished, creating that batch file
createT = int(create) + 1
for i in range(1, createT): # Runs a set amount of times
copyName = "%s.py" % str(i) # Creates the name for the file
copy = open(copyName, 'w+') # Opens/creates the file for editing
copy.write(indata) # Writies the indata to the file opened
copy.close # Closes that file
batName = "%s.bat" % str(i)
bat = open(batName, 'w+')
It is not finished but hopefully you get the gist. The argv at the beginning is so I can change the amount of copies made, that will be deleted later as I evolve the code but for now I like it there.
I have currently tried the following to find the path:
import os
print os.path.abspath(__file__)
print os.path.dirname(os.path.abspath(__file__))
print os.path.dirname(__file__)
test = os.path.dirname(__file__)
a, b, c, d, e, f, g, h, i = test.split("\\")
print c
What I want to happen (or think I want to happen) is for the path to be found, then split into pieces (either each directory or break off everything after the username). Then I want to append the document folder tag to the end. For the batch instead of the document tag it will be for the desktop.
among a few others that people have posted. I hope this helps!
Your code snippet returns a string. Just take that string and edit to make the path you want. I'm on a mac so I can't test with an actual windows directory but I'll try to make it look Windows-ish. For instance, lets say this code:
directory_path = os.path.dirname(os.path.abspath(__file__))
print(directory_path)
gives you:
C:\Users\username\AppData
You can use the split function to break the path into pieces (docs).
stuff = path_string.split('\')
print(stuff)
Code output:
['C:', 'Users', 'username', 'AppData']
You can use the pieces create the path you want and then use it to write the file. So, if you want the username folder just loop until you find it. Some example code is below (just an example to get you started - read up on Python if you need help understanding the code).
username = ""
for i in range(0, len(stuff)):
if stuff[i] == "Users":
username = stuff[i + 1]
Not sure if that answers your question but hope it helps.
Am I correct that you are trying to figure out how to make a file path to some location on the user's directory without knowing who the user is going to be that is executing the program?
You may be able to take advantage of environment variables for this. For instance, I can get a file path to the C://Users/username/ directory of whoever is executing the code with:
my_path = os.path.join("C:\\", "Users", os.getenv("USERNAME"))
Where os.getenv("USERNAME") returns the value of the USERNAME environment variable (should be the name of the user that is currently logged on).
You can list all of the available environment variables and their values in Python with:
for key, val in os.environ.items():
print("{} \t {}\n".format(key, val)) # or however you want to prettify it
You may get lucky and find an environment variable that gives you most of the path to begin with.
In general, os.path.join(), os.path.relpath(), and os.path.abspath() combined with some environment variables might be able to help you. Check out the os documentation and os.path documentation.
Many times when modifying a path, I am looking to add/remove folders. Here is my simple method for adding a path, e.g. if I want to move the path of an object into a folder added_path='/train/.
Since my paths are usually uniform, I check the last split characters in the first file location. Usually, my experience is that windows have \\ at the end while Mac and Linux have `/', which makes this work across operating systems. (note: if the paths are not uniform, you obviously place the if-else in the for-loop.)
if '\\' in data[0].img_file:
split_char = '\\'
else:
split_char = '/'
for img in data:
img_path = img.img_file.split(split_char)
label_path = img.label_file.split(split_char)
img.img_file = '/'.join(img_path[:-1]) + added_path + img_path[-1]
img.label_file = '/'.join(label_path[:-1]) + added_path + label_path[-1]
So, this for loop uses all the folders up until the file name, where we insert the extra folder, and then, at last, add the file name.
Example input path: 'data/combined/18.png'
Example output path: 'data/combined/train/18.png'

Optparse to find a string

I have a mysql database and I am trying to print all the test result from a specific student. I am trying to create a command line where I enter the username and then it will shows his/her test result.
I visited this page already but I couldn't get my answer.
optparse and strings
#after connecting to mysql
cursor.execute("select * from database")
def main():
parser = optparse.OptionParser()
parser.add_option("-n", "--name", type="string", help = "student name")
(options, args) = parser.parse_args()
studentinfo = []
f = open("Index", "r")
#Index is inside database, it is a folder holds all kinds of files
Well, the first thing you should do is not use optparse, as it's deprecated - use argparse instead. The help I linked you to is quite useful and informative, guiding you through creating a parser and setting the different options. After reading through it you should have no problem accessing the variables passed from the command line.
However, there are other errors in your script as well that will prevent it from running. First, you can't open a directory with the open() command - you need to use os.listdir() for that, then read the resulting list of files. It is also very much advisable to use a context manager when open()ing files:
filelist = os.listdir("/path/to/Index")
for filename in filelist:
with open(filename, "r") as f:
for line in f:
# do stuff with each line
This way you don't need to worry about closing the file handler later on, and it's just a generally cleaner way of doing things.
You don't provide enough information in your question as to how to get the student's scores, so I'm afraid I can't help you there. You'll (I assume) have to connect the data that's coming out of your database query with the files (and their contents) in the Index directory. I suspect that if the student scores are kept in the DB, then you'll need to retrieve them from the DB using SQL, instead of trying to read raw files in the filesystem. You can easily get the student of interest's name from the command line, but then you'll have to interpolate that into a SQL query to find the correct table, select the rows from the table corresponding to the student's test scores, then process the results with Python to print out a pretty summary.
Good luck!

Categories

Resources