Python Login Screen Tkinter - python-3.x

I have been searching for an answer to this question for a couple days and all I can find is info about how to create a form for logging in. I am able to this just fine, my issue is a little more granular. I know how to capture data entered into the entry fields in tkinter with the .get() function.
I have multiple classes that serve as different parts of my program with various functions etc, but currently I have hard coded username, password, host, and database into the necessary portions of the program. This is a security risk and I would like to pass the login information to those locations allowing a user to login once and be able to enter their SQL Queries and be done, but upon closing the program/logging out these fields revert to being empty.
I have been reading about the use of setting a variable to be global, but this doesn't seem to be the best way to go about doing so since many people are saying that you should avoid globals if at all possible.
I think it should look like this:
import mysql.connector as mysql
from tkinter import *
class Login:
def__init__(self, login):
self.login=login
login.title("Login Screen")
global self.cnxn
self.cnxn=mysql.connect(
host=entry1.get(),
user=entry2.get(),
passwd=entry3.get(),
database=entry4.get())
self.entry1=Entry(login)
self.entry2=Entry(login)
self.entry3=Entry(login)
self.entry4=Entry(login)
self.entry1.pack()
self.entry2.pack()
self.entry3.pack()
self.entry4.pack()
class Other:
def__init__(self, other):
self.login=other
other.title("Login Screen")
def add():
c=self.cnxn
c.cursor()
self.cnxn.commit()
self.cnxn.close()
main=Tk()
Login(main)
main.mainloop()
My understanding of using globals is very limited, but I believe I would be able to pass the global variable to other classes and functions.
Is there a better way to do what I am trying to do?

If you wish to define a global variable for a specific class you can simply add the variable above the class initialiser as follows...
class myClass:
my_global_var = "Hi"
def __init__(self):
print(myClass.my_global_var)
myClass()
You can acccess the variables using this format classname.globalvariable you can now access this variable anywhere in your program.

Related

Building a good class method

I've built a class to ask a user a question, based on a type.
class Question:
def __init__(self, subject):
self.subject = subject
self.question = f"Enter the {subject} to be created. You may end this by typing 'DONE':\n"
self.still_needed = True
def ask_question(self):
ans_list = []
running = True
while running:
var = input(f"Enter {self.subject}?\n")
if var.lower() == 'done':
running = False
else:
ans_list.append(var)
return ans_list
The idea is to have a question model, to create lists of items.
This seems to work well with the following code in main.
roles = Question(subject="role").ask_question()
This creates a list from the Queue Class and uses it's method ask question to generate the list. As far as I can tell the object is then destroyed, as it's not saved to a variable.
My question, being new to Python and OOP is, does this seem like a solid and non-confusing way, or should I refractor? If so, what does the community suggest?
MY OPINION
I guess it depends on you. For one, one of the main purposes of using a class is to create an instance with it later on. Classes are objects ,or "categories" as I like to call them, that you use when there are distinctive types of instances in your project.
Given your code snippet, I can't really suggest anything, I don't know the usage of self.question and self.still_needed. However, if I were to base my opinion on just this part: roles = Question(subject="role").ask_question(), then I'd definitely go with using a function instead. As you've said,
As far as I can tell the object is then destroyed, as it's not saved
to a variable.
ALTERNATIVE SOLUTION
Use decorators → the one with # symbol
In this case, #staticmethod is the way to go!
What are staticmethods? The staticmethod decorator is a way to create a function in a class. So instead of it becoming a method, it can be treated as a function (without self parameter). This also means that a static method bounds to the class rather than its object. Consequently, static methods do not depend on objects (hence, you don't need to create an object for you to use it). Example:
class SomeMathStuff():
#staticmethod
def AddSomeNumbers(iterable):
return sum(iterable)
result = SomeMathStuff.AddSomeNumbers([1, 2, 3])
# result = 6
As you can see, I did not need to create an object, instead I just needed to call its class to use it. Word of warning, most Python programmers argue that this is the un-Pythonic way, but I wouldn't worry too much about it. Hell, even I use these methods sometimes. In my defense, this is a good and efficient way to organize your project. With this, you can apply class methods globally and you can "categorize" them in certain classes you find suitable.
Anyway, this is all I have! I apologize if I misinformed you in any way.
ADDITIONAL INFROMATION ... in case I wasn't the best teacher
https://www.programiz.com/python-programming/methods/built-in/staticmethod
Difference between staticmethod and classmethod
https://softwareengineering.stackexchange.com/questions/171296/staticmethod-vs-module-level-function

APscheduler and Pyramid python

I'm trying to use the wonder apscheduler in a pyarmid api. The idea is to have a background job run regularly, while we still query the api for the result from time to time. Basically I use the job in a class as:
def my_class(object):
def __init__(self):
self.current_result = 0
scheduler = BackGroundScheduler()
scheduler.start()
scheduler.add_job(my_job,"interval", id="foo", seconds=5)
def my_job():
print("i'm updating result")
self.current_result += 1
And outside of this class (a service for me), the api has a POST endpoint that returns my_class instance's current result:
class MyApi(object):
def __init__(self):
self.my_class = MyClass()
#view_config(request_method='POST')
def my_post(self):
return self.my_class.current_result
When everything runs, I see the prints and incrementation of value inside the service. But current_result stays as 0 when gathered from the post.
From what I know of the threading, I guess that the update I do is not on the same object my_class but must be on a copy passed to the thread.
One solution I see would be to update the variable in a shared intermediate (write on disk, or in a databse). But I wondered if that would be possible to do in memory.
I manage to do exactly this when I do this in a regular script, or with one script and a very simple FLASK api (no class for the API there) but I can't manage to have this logic function inside the pyramid api.
It must be linked to some internal of Pyramid spawning my api endpoint on a different thread but I can't get right on the problem.
Thanks !
=== EDIT ===
I have tried several things to solve the issue. First, the instance of MyClass used is intitialized in another script, follow a container pattern. That container is by default contained in all MyApi instances of pyramid, and supposed to contain all global variables linked to my project.
I also define a global instance of MyClass just to be sure, and print its current result value to compare
global_my_class = MyClass()
class MyApi(object):
def __init__(self):
pass
#view_config(request_method='POST')
def my_post(self):
print(global_my_class.current_result)
return self.container.my_class.current_result
I check using debug that MyClass is only spawned twice during the api execution (one for the global variable, one inside the container. However.
So what I see in logging are two values of current_result getting incremented, but at each calls of my_post I only get 0s.
An instance of view class only lives for the duration of the request - request comes in, a view class is created, produces the result and is disposed. As such, each instance of your view gets a new copy of MyClass() which is separate from the previous requests.
As a very simple solution you may try defining a global instance which will be shared process-wide:
my_class = MyClass()
class MyApi(object):
#view_config(request_method='POST')
def my_post(self):
return my_class.current_result

Nested Classes in Python 3

I am trying to create a nested class to perform sum or multiplication of the arguments passed in each subclass.
The below example helps me perform action within the class, however I am unable to find any documentation which would help me with inheriting the attributes from the Parent Class to child.
Recently I came across an article which highlights "nested classes can't access any members of their outer classes at compile-time.". Is there a better way to pass the values between Classes? I tried using global variables, but would like to avoid setting many global variables while I scale this logic to extract my entire datacenter's inventory, perform some calculations and again pass to another class.
class Class1:
firstnumber=0
def __init__(self,arg):
self.firstnumber=arg
class Class2:
def __init__(self,arg):
self.secondnumber=arg
def sumit(self):
return Class1.firstnumber+Class1.Class2.secondnumber
print(Class1(5).firstnumber)
print(Class1(6).Class2(4).secondnumber)
print(Class1(4).Class2(10).sumit())
I would like to perform calculations with
Class1(variable1).Class2(variable2).Class3(variable3).sum() or
Class1(variable1).Class2(variable2).Class3(variable3).multiple() and eventually be able to do following
Datacenter('DC1').GetServer('ServerName').GetStorageCapacity('NFS').Used()
Datacenter('DC1').GetServer('ServerName').GetStorageCapacity('NFS').Free()
http://momentaryfascinations.com/programming/bound.inner.classes.for.python.html
i may be wrong but to my understanding anything you put in between the class() and the init statement is permanent and unchangable. you shouldn't need to create seperate classes for each number. create different instances of the same class.
class numbers:
def __init__(self,arg):
self.arg = arg
c1 = numbers(3)
c2 = numbers(5)
i don't know how you would add the arg variables together maybe someone else can fill in what i'm missing.

best practices for passing initialization arguments to superclasses?

I'm trying to figure out the best way to initialize sub/superclasses in Python3. Both the base and subclasses will take half a dozen parameters, all of which will be parsed from command line arguments.
The obvious way to implement this is to parse all the args at once, and pass them all in:
class Base:
def __init__(self, base_arg1, base_arg2, base_arg3):
class Sub(Base):
def __init__(self, sub_arg1, sub_arg2, sub_arg3,
base_arg1, base_arg2, base_arg3):
super().__init__(self, base_arg1, base_arg2, base_arg3)
main():
# parse args here
options = parser.parse_args()
obj = Sub(options.sub_arg1, options.sub_arg2, options.sub_arg3,
options.base_arg1, options.base_arg2, options.base_arg3)
If I have a Sub-subclass (which I will), things get really hairy in terms of the list of arguments passed up through successive super().init() calls.
But it occurs to me that argparse.parse_known_args() offers another path: I could have each subclass parse out the arguments it needs/recognizes and pass the rest of the arguments up the hierarchy:
class Base:
def __init__(self, args):
base_options = base_parser.parse_known_args(args)
class Sub(Base):
def __init__(self, args):
(sub_options, other_args) = sub_parser.parse_known_args(args)
super().__init__(self, other_args)
main():
obj = Sub(sys.argv)
This seems cleaner from an API point of view. But I can imagine that it violates some tenet of The Way Things Are Done In Python and is a bad idea for all sorts of reasons. My search of the web has not turned up any examples either way - could the mighty and all-knowing mind of Stack Overflow help me understand the Right Way to do this?
Look inside the argparse.py code. An ArgumentParser is a subclass of an _ActionsContainer. All the actions are subclasses of Action.
When you call
parser.add_argument('foo', action='store_action', ...)
the parameters are passed, mostly as *args and **kwargs to _StoreAction, which in turn passes them on to its supper (after a setting some defaults, etc).
As a module that is mean to be imported, and never run as a stand along script it does not have a if __name__.... block. But often I'll include such a block to invoke test code. That's the place to put the commandline parser, or at least to invoke it. If might be defined in a function in the body, but it normally shouldn't be called when module is imported.
In general argparse is a scripting tool, and shouldn't be part of a class definitions - unless you are a subclassing ArgumentParser to add some new functionality.
You might also want to look at https://pypi.python.org/pypi/plac. This package provides a different interface to argparse, and is a good example of subclassing this parser.
Thanks hpaulj! I think your response helped me figure out an even simpler way to go about it. I can parse all the options at the top level, then just pass the option namespace in, and let each subclass pull out the ones it needs. Kind of face-palm simple, compared to the other approaches:
class Base:
def __init__(self, options):
base_arg1 = options.base_arg1
base_arg2 = options.base_arg2
class Sub(Base):
def __init__(self, options):
super().__init__(self, options) # initialize base class
sub_arg1 = options.sub_arg1
sub_arg2 = options.sub_arg2
main():
options = parser.parse_args()
obj = Sub(options)

Add renderer in #view_config from configuration?

How do I supply a configured value to a #view_config-decorated function or class?
E.g.
#view_config(route_name='example', renderer=some_config['template.name'])
class MyClass(BaseView):
...
Or
#view_defaults(route_name='example', renderer=some_config['template.name2'])
class MyClass2(BaseView):
...
Or
#view_config(route_name='example', renderer=some_config['template.name3'])
def method3(request):
...
It's very hard to know where to start, as I'm trying to edit a pyramid plugin, which pulls together its config in an includeme function, so it doesn't have anything obvious that I can include, and it's hard to know what's available to the #view_config decorator.
You can add views using declarative configuration (what you are doing now using #view_config or alternatively using imperative configuration by calling config.add_view() method.
In this case, as you need to access the Pyramid registry and settings file, it is easier to do adding the views imperatively.
In your __init__.py you can do:
settings = config.registry.settings
# You need to call config.add_route("foobar") to map view to URL also
config.add_view('views.MyClass', route_name="foobar", renderer=settings['template.name3'])
Then in your views.py:
class MyClass(BaseView):
pass
#view_config() and add_view() arguments are equal.
I thin kyou can also mix view_config and add_view() arguments for the same view, but I am not sure aobut this. Hope this helps.

Resources