Python output to command line; Error not defined - python

I am trying to write a script that takes one argument and writes the output to the command window. For some reason I am getting the error:
NameError: name 'month' not defined
Here is the entire script:
import sys
hex = str(sys.argv)
sys.stdout.write (month(hex) + " " + day(hex) + ", " + year(hex) + " " + hour(hex) + ":" + minute(hex) + ":" + second(hex))
def year (hex):
year = int(hex[0:2], 16)
year = year + 1970
return str(year)
def month (hex):
month = int(hex[2:4], 16)
if month == 0:
month = "January"
return month
elif month == 1:
month = "February"
return month
elif month == 2:
month = "March"
return month
elif month == 3:
month = "April"
return month
elif month == 4:
month = "May"
return month
elif month == 5:
month = "June"
return month
elif month == 6:
month = "July"
return month
elif month == 7:
month = "August"
return month
elif month == 8:
month = "September"
return month
elif month == 9:
month = "October"
return month
elif month == 10:
month = "November"
return month
else:
month = "December"
return month
def day (hex):
day = int(hex[4:6], 16)
return str(day)
def hour (hex):
hour = int(hex[6:8], 16)
if hour < 10:
return "0" + str(hour)
else:
return str(hour)
def minute (hex):
minute = int(hex[8:10], 16)
if minute < 10:
return "0" + str(minute)
else:
return str(minute)
def second (hex):
second = int(hex[10:12], 16)
if minute < 10:
return "0" + str(second)
else:
return str(second)
When I used an online python interpreter to run it, the functions worked fine. I just don't know how to run it from the command line and send the output back to the command window. Thanks

In python a file is parsed line by line from top to bottom, so the functions month,year,hour,minute and second are not defined yet for this line:
sys.stdout.write (month(hex) + " " + day(hex) + ", " + year(hex) + " " + hour(hex) + ":" + minute(hex) + ":" + second(hex))
Move these function definitions above this line.
And using a local variable with same name as the function name is not a good idea.
As sys.argv returns a list (with first element being the filename), so you can't apply hex over it. Apply hex on the items of the list, i.e hex( int(sys.argv[1]) )
>>> lis = ['foo.py', '12']
>>> hex( int(lis[1]) ) #use `int()` as hex expects a number
'0xc'

Put the line sys.stdout.write... after your function definitions.
Please, don't use month for both your function and a variable inside this function.

Related

Return a new instance from a class method

I've implemented a date class, which calculates the next day's date and the previous day's date.
eg. if today is 3/26/2022 (MM/DD/YYYY) then my method nextday gives 3/27/2022.
However, instead of returning a string, I am trying to return an instance but it's not working properly. It's calculating the day correctly but changes the original instance.
This is my class:
class Date:
"""
Assigning class arguments
"""
min_year = 1800
dow_jan1 = "Wednesday"
def __init__(self,month=1,day=1,year=min_year):
"""
Assigning instance arguments and checking the validity of dates.
If Not valid then an Exception is raised.
"""
self.c_month = month
self.c_day = day
self.c_year = year
if self.c_year < self.min_year:
raise Exception("Invalid Year")
elif self.c_month <1 or self.c_month > 12:
raise Exception("Invalid Month")
elif self.c_day<1 or self.c_day > 31:
raise Exception("Invalid Day")
else:
if self.c_month == 2:
if self.year_is_leap(self.c_year):
if self.c_day<1 or self.c_day > 29:
raise Exception("Invalid Day")
else:
if self.c_day<1 or self.c_day > 28:
raise Exception("Invalid Day")
else:
months_31_days = [1,3,5,7,8,10,12]
if self.c_month in months_31_days:
if self.c_day<1 or self.c_day > 31:
raise Exception("Invalid Day")
else:
if self.c_day<1 or self.c_day > 30:
raise Exception("Invalid Day")
def year_is_leap(self,year=None):
"""
Finds if a year is Leap or not
Parameters:
year : takes a year which is to be checked
however if a year is not provided then the instance argument year (self.c_year)
is set as default value
"""
if year is None:
year = self.c_year
if (year % 4) == 0:
if (year % 100) == 0:
if (year % 400) == 0:
return True
else:
return False
else:
return True
else:
return False
def __str__(self):
"""
returns the date in suitable format
eg. 2/14/1900 => February 14, 1900
"""
months = {1:"January",2:"February",3:"March",4:"April",
5:"May",6:"June",7:"July",8:"August",9:"September",
10:"October",11:"November",12:"December"}
return "{} {}, {}".format(months[self.c_month],self.c_day,self.c_year)
def nextday(self):
"""
Returns next date in date object
"""
leap_year = self.year_is_leap(self.c_year)
#print(leap_year)
if self.c_month in (1, 3, 5, 7, 8, 10, 12):
month_length = 31
elif self.c_month == 2:
if leap_year:
month_length = 29
else:
month_length = 28
else:
month_length = 30
if self.c_day < month_length:
self.c_day += 1
else:
self.c_day = 1
if self.c_month == 12:
self.c_month = 1
self.c_year += 1
else:
self.c_month += 1
print("The next date is [mm-dd-yyyy] %d-%d-%d." % (self.c_month, self.c_day,self.c_year))
return self #Date(self.c_month,self.c_day,self.c_year) #Date #self.__class__()
```
I've tried to return `self`, `Date()`, `Date(self.c_month,self.c_day,self.c_year)` and `self.__class__()`, however none of it worked.
When I run:
firstdate = Date(1,1,Date.min_year)
print(firstdate)
print("The date after ", firstdate, "is", firstdate.nextday())
I am getting the output:
January 1, 1800
The next date is [mm-dd-yyyy] 1-2-1800.
The date after January 2, 1800 is January 2, 1800
The most straightforward solution will be creating a new instance of Date with same values as self (basically copy it) and work with it, not changing self:
class Date:
# other methods here
def nextday(self):
"""
Returns next date in date object
"""
new_date = Date(self.c_month, self.c_day, self.c_year)
is_leap_year = new_date.year_is_leap(new_date.c_year)
if new_date.c_month in {1, 3, 5, 7, 8, 10, 12}:
month_length = 31
elif new_date.c_month == 2:
month_length = 28 + is_leap_year
else:
month_length = 30
if new_date.c_day < month_length:
new_date.c_day += 1
else:
new_date.c_day = 1
if new_date.c_month == 12:
new_date.c_month = 1
new_date.c_year += 1
else:
new_date.c_month += 1
print("The next date is [mm-dd-yyyy] %d-%d-%d." % (new_date.c_month, new_date.c_day,new_date.c_year))
return new_date
You could also implement some convenience methods (e.g. .copy to copy the date or __format__ to print the date, but that's out of question scope)
The problem is that you change the object attributes. For example on nextday method, you write self.c_day += 1, you are changing the object itself.
Instead, if you want to return a new Date, you need to write c_day += 1 then return Date(c_month, c_day, c_year)

Cannot operate on year value of regular expression

This is my first question here so please forgive and educate on any formatting errors. I am new to Python and going through automate the boring stuff. Decided to expand the date detection project by using the clipboard and formatting some things also. The problem I have is in any operation taken on the year part of the REGEX.
I have commented out my last attempt to validate the year and gave up and changed the REGEX to only find dates from 1000 to 2999 and skipped code validation of the dates.
I now need to validate leap years but I'm back to having to work with the year variable, but once again no operation has any effect.
Basically the problem is I can extract the year value and display it but I cannot modify it or do checks against it.
#! python3
#! detect dates in a block of text
import pyperclip
import re
#!import numpy as np
text = str(pyperclip.paste())
def datedetection(text):
dateRegex = re.compile(
r"""(
(\d|\d\d) #! match day
(/{1}) #! match /
(\d|\d\d) #! match month
(/{1}) #! match /
([1|2][0-9][0-9][0-9]) #! match year
)""",
re.VERBOSE,
)
matches = []
for groups in dateRegex.findall(text):
day = str(groups[1])
slash1 = str(groups[2])
month = str(groups[3])
slash2 = str(groups[4])
year = str(groups[5])
month_range_30 = ["04", "06", "09", "11"]
month_range_31 = ["01", "03", "05", "07", "08", "10", "12"]
month_range_Feb = ["02"]
#!year_range = np.arange(1000, 3000, 1).tolist()
if len(day) == 1:
day = "0" + day
else:
day = day
if len(month) == 1:
month = "0" + month
else:
month = month
if month in month_range_31:
if int(day) > 31:
day = "Too many days in a month with only 31 days."
slash1 = month = slash2 = year = ""
elif month in month_range_30:
if int(day) > 30:
day = "Too many days in a month with only 30 days."
slash1 = month = slash2 = year = ""
elif month in month_range_Feb:
if int(day) > 29:
day = "Too many days in February."
slash1 = month = slash2 = year = ""
elif int(month) > 12:
day = "Found an invalid month."
slash1 = month = slash2 = year = ""
elif month in month_range_Feb:
if (
int(day) == 29
and (int(year) % 4 == 0)
and (int(year) % 400 == 0)
and (int(year) % 100 == 0)
):
day = day
elif month in month_range_Feb:
if (
int(day) == 29
and (int(year) % 4 == 0)
and (int(year) % 100 != 0)
):
day = "Found an invalid leap year."
slash1 = month = slash2 = year = ""
#!elif year not in year_range:
#!day = "Year is out of range."
#!slash1 = month = slash2 = year = ""
dates = "".join([day, slash1, month, slash2, year])
matches.append(dates)
if len(matches) > 0:
pyperclip.copy("\n".join(matches))
print("Copied to clipboard:")
print("\n".join(matches))
else:
print("No dates found.")
datedetection(text)
In my approach to this project, I considered validating the days, months, and year ranges as part of the regular expression. I then defined functions to check for the leap year, and validate the number of days according to the months.
I found that way simpler and easier to understand and follow. As below:
dateRegex = re.compile(r'([0-3][0-9])/([0-1][0-9])/([1-2][0-9]{3})')
def is_leap_year(year):
year = int(year)
if year % 4 == 0:
if year % 100 == 0:
return year % 400 == 0
else:
return True
else:
return False
def is_valid_date(day, month, year):
if month == '02':
if is_leap_year(year):
return int(day) <= 29
else:
return int(day) <= 28
elif month in ['04', '06', '09', '11']:
return int(day) <= 30
else:
return int(day) <= 31
You can find the rest of my code below.
https://gist.github.com/alialbusaidi/f56e4c9342f622434f8bff0549f94884
The problem was the operations before the year operations. The day and month operations were overwriting the year values. Not entirely sure how or why at this point, but moving the year code above the day and month code has started to fix the issue.

Threading Error: NameError: name 'datelabelstringvar' is not defined [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
In python, I want a function to run at the same time as my normal script. I searched the internet and found threading, however, when I implement it and run the code, the error NameError: name 'datelabelstringvar' is not defined appears. I don't know what is wrong but when I remove threading and assign the function to a button (which I don't want just to be clear, I want it to be automatic), it works fine.
Code:
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
from numerize import numerize
import pygame
import os
import random
from datetime import datetime
import threading
import time
wholedate = datetime.date(datetime.now())
date = wholedate.strftime("%d")
month = wholedate.strftime("%m")
year = wholedate.strftime("%Y")
def advancetime():
global date
global month
global year
threading.Timer(5.0, advancetime).start()
if month == "09" or month == "04" or month == "06" or month == "11":
date = int(date) + 1
if date > 30:
date = 1
month = int(month) + 1
if month > 12:
month = 1
year = int(year) + 1
fixdate()
fixmonth()
datelabelstringvar.set(str(date) + "/" + str(month) + "/" + str(year))
return
if month == "01" or month == "03" or month == "05" or month == "07" or month == "08" or month == "10" or month == "12":
date = int(date) + 1
if date > 31:
date = 1
month = int(month) + 1
if month > 12:
month = 1
year = int(year) + 1
fixdate()
fixmonth()
datelabelstringvar.set(str(date) + "/" + str(month) + "/" + str(year))
return
if month == "02":
date = int(date) + 1
if date > 31:
date = 1
month = int(month) + 1
if month > 12:
month = 1
year = int(year) + 1
fixdate()
fixmonth()
datelabelstringvar.set(str(date) + "/" + str(month) + "/" + str(year))
def calendarOnClose():
root.deiconify()
calendarwindow.destroy()
def calendar():
global datelabelstringvar
global calendarwindow
root.withdraw()
calendarwindow = Toplevel()
calendarwindow.title("Calendar")
calendarwindow.geometry("400x350+300+100")
calendarwindow.protocol("WM_DELETE_WINDOW", calendarOnClose)
datelabelstringvar = StringVar()
datelabelstringvar.set(str(date) + "/" + str(month) + "/" + str(year))
datelabel = Label(calendarwindow, textvariable=datelabelstringvar).grid(row="0", column="0")
Button(calendarwindow, text="Advance Time", command=advancetime).grid(row="1", column="0")
totalfruitclickerstringvar = StringVar()
totalfruitclickerstringvar.set("Fruit Clicked: " + str(totalfruitclicked))
Label(calendarwindow, textvariable=totalfruitclickerstringvar).grid(row="2", column="0")
root = Tk()
root.title("Fruit Clicker")
root.geometry("400x350+300+100")
calendarbutton = Button(root, text="Calendar", fg="White", bg="Black", width="11", command=calendar)
calendarbutton.grid(row="8", column="0")
advancetime()
root.mainloop()
How do I fix this error? Thanks.
EDIT:
Full Error:
Traceback (most recent call last):
File "C:\Users\colli\Documents\GitHub\FruitClicker\windows\main.py", line 1708, in <module>
advancetime()
File "C:\Users\colli\Documents\GitHub\FruitClicker\windows\main.py", line 113, in advancetime
datelabelstringvar.set(str(date) + "/" + str(month) + "/" + str(year))
NameError: name 'datelabelstringvar' is not defined
Your code makes several references to a datelabelstringvar variable. However, you never define it. That's what Python is saying.
EDIT:
It doesn't appear that you ever call the calendar function where the variable is defined.

Python program saying variable 'dateNumber' is not defined

def dateCalculationNorm(year):
a = year%19
b = year%4
c = year%7
d = (19*a + 24)%30
e = (2*b + 4*c + 6*d + 5)%7
dateNumber = 22 + d + e
return dateNumber
def dateCalculationSpecial(year):
a = year%19
b = year%4
c = year%7
d = (19*a + 24)%30
e = (2*b + 4*c + 6*d + 5)%7
dateNumber = 15 + d + e
return dateNumber
def dateOutput(year, date):
print("The date of Easter in the year {0} is {1}.".format(year, date))
def main():
print("Easter Date Calculator")
print()
year = eval(input("Enter the year: "))
if year >= 1900 and year <= 2099:
dateCalculationNorm(year)
if dateNumber > 31:
date = "April " + str(dateNumber - 31)
dateOutput(year, date)
else:
date = "March " + str(dateNumber)
dateOutput(year, date)
elif year == 1954 or year == 1981 or year == 2049 or year == 2076:
dateCalculationSpecial(year)
if dateNumber > 31:
date = "April " + str(dateNumber - 31)
dateOutput(year, date)
else:
date = "March " + str(dateNumber)
dateOutput(year, date)
else:
print("Sorry, but that year is not in the range of this program.")
if __name__ == '__main__':
main()
I am having trouble getting main() to accept dateNumber in the line following
(if year >= 1900 and year <=2099) Python is saying that dateNumber is not defined. I tried making dateNumber global at the beginning of the program and that worked (albeit with a warning from Python), but I know that's the sloppy way to get this program working.
Any help is very much appreciated.
You need to instantiate dateNumber.
if year >= 1900 and year <= 2099:
dateNumber = dateCalculationNorm(year) # Instantiate here.
if dateNumber > 31:
date = "April " + str(dateNumber - 31)
dateOutput(year, date)
else:
date = "March " + str(dateNumber)
dateOutput(year, date)
As it stands, there's nothing like that inside your main() function. There's no need to set it to a global either.

calling a variable from another function in python 3.3?

I know that this has been asked before, but I cant for the life of me understand it. I'm trying to create a simple program that gets two dates, and counts shows how many days are left between them.
This is my current code:
month = 0
day = 0
year = 0
def getDate(): #gets the current date
global month
global day
global year
print( 'What is the current month?' )
month = month + int(input())
print( 'What is the current day?' )
day = day + int(input())
print( 'What is the current year?' )
year = year + int(input())
print( 'The current date is ' + str(month) + '/' + str(day) + '/' + str(year) + '. Is this correct?' )
YESNO = input() #confirms date
if YESNO == 'YES' or YESNO == 'yes':
print( 'Okay.' )
else:
getDate()
newMonth = 0
newDay = 0
newYear = 0
def newDate(): #gets the desired countdown date
global newMonth
global newDay
global newYear
print( 'What is the desired countdown month?' )
newMonth = newMonth + int(input())
print( 'What is the desired countdown day?' )
newDay = newDay + int(input())
print( 'What is the desired countdown year?' )
newYear = newYear + int(input())
print( 'The desired countdown date is ' + str(newMonth) + '/' + str(newDay) + '/' + str(newYear) + '. Is this correct?' )
YESNO = input() #confirms date
if YESNO == 'YES' or YESNO == 'yes':
print( 'Okay.' )
else:
newDate()
def COUNTDOWN(): #prints countdown
global newMonth
global newDay
global newYear
global month
global day
global year
if newMonth < Month:
countDownMonth = int(Month) - int(newMonth)
else:
countDownMonth = int(newMonth) - int(Month)
if newDay < Day:
countDownDay = int(Day) - int(newDay)
else:
countDownDay = int(newDay) - int(Day)
if newMonth < Year:
countDownYear = int(Year) - int(newYear)
else:
countDownYear = int(newYear) - int(Year)
print( countDownMonth + '/' + countDownDay + '/' + countDownYear )
getDate()
newDate()
COUNTDOWN()
EDIT:
I apologize, I didn't realize it wasn't indented.
EDIT:
My question is how do I create a cross-function variable?
The global keyword in python is used to rebind a global variable in a local context. That being said, it is generally good practice to avoid the usage of the global keyword whenever possible.
In the code that you posted, it is necessary to use global in the functions getDate and newDate in order to bind those names in the global environment. However, in COUNTDOWN, because you are not rebinding the names and are only accessing the values bound to those names, global is not necessary.
For more information look here: Use of "global" keyword in Python
I just make your code workable as below:
month = 0
day = 0
year = 0
newMonth = 0
newDay = 0
newYear = 0
def getDate(): #gets the current date
global month
global day
global year
print( 'What is the current month?' )
month = month + int(input())
print( 'What is the current day?' )
day = day + int(input())
print( 'What is the current year?' )
year = year + int(input())
print( 'The current date is ' + str(month) + '/' + str(day) + '/' + str(year) + '. Is this correct?' )
YESNO = raw_input() #confirms date
print YESNO
if YESNO == 'YES' or YESNO == 'yes':
print( 'Okay.' )
else:
getDate()
def newDate(): #gets the desired countdown date
global newMonth
global newDay
global newYear
print( 'What is the desired countdown month?' )
newMonth = newMonth + int(input())
print( 'What is the desired countdown day?' )
newDay = newDay + int(input())
print( 'What is the desired countdown year?' )
newYear = newYear + int(input())
print( 'The desired countdown date is ' + str(newMonth) + '/' + str(newDay) + '/' + str(newYear) + '. Is this correct?' )
YESNO = raw_input() #confirms date
if YESNO == 'YES' or YESNO == 'yes':
print( 'Okay.' )
else:
newDate()
def COUNTDOWN(): #prints countdown
global newMonth
global newDay
global newYear
global month
global day
global year
if newMonth < month:
countDownMonth = int(month) - int(newMonth)
else:
countDownMonth = int(newMonth) - int(month)
if newDay < day:
countDownDay = int(day) - int(newDay)
else:
countDownDay = int(newDay) - int(day)
if newMonth < year:
countDownYear = int(year) - int(newYear)
else:
countDownYear = int(newYear) - int(year)
print( str(countDownMonth) + '/' + str(countDownDay) + '/' + str(countDownYear) )
getDate()
newDate()
COUNTDOWN()
In my env, this code is working, but i am not sure whether the output correct or not.
use the global keyword, like so:
def function():
global variable
this basically says, I want to access variable, even though I know it is global I still want it anyway.
Only use this if you are Changing the variable, not just using whatever is inside it.
e.g.,
def example():
global eg
eg = 1
Here we use global because we are changing eg's content. If we were to instead, USE eg's content to do something different we would do this:
def example(eg):
eg2 = eg
Here we are saying, 'I want to use the value that eg contains, but I dont want to change it'.
Then we have declared eg2 to be the same as eg, but we have not changed eg
If you wanted to then use the outcome of the function example, you would add a 'return' line.
def example(eg):
eg2 = eg
return eg
then we would call the function like so:
eg3 = example(eg)
This puts the result of example into eg3.
Hope this helps :)

Categories