From mehrotra.saket at gmail.com Wed Aug 1 00:07:11 2018 From: mehrotra.saket at gmail.com (Saket Mehrotra) Date: Wed, 1 Aug 2018 09:37:11 +0530 Subject: [Tutor] SSL Error In-Reply-To: References: Message-ID: Hi I am also not using any Open SSL package. I have just added " import requests" in py file. And when I run the module I get the SSL package error ,not sure why. Thanks Saket On Tue, Jul 31, 2018 at 10:28 PM, Marc Tompkins wrote: > This is a general Python tutor group; I'm not sure anybody here can help > you with the OpenSSL package (I've definitely never used it myself.) We're > all willing to help, but this might not be the right place to ask this > question. > > More to the point, though, when you ask questions on this list it's best > to just cut and paste BOTH your code and the actual error > message/traceback; from the bit that you've posted, it sounds like it might > be as simple as a typo, but we can't really tell without seeing your code. > > On Mon, Jul 30, 2018 at 7:52 PM, Saket Mehrotra > wrote: > >> Hi >> >> I am trying to run import requests in a py file but I am getting below >> error ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, >> AttributeError: module 'ssl' has no attribute 'PROTOCOL_SSLv23' >> >>> >> >> I tried to execute below from the terminal but it still remains >> unresolved. >> >> sudo easy_install --upgrade pip >> >> I've also had to run: >> >> sudo pip uninstall pyopenssl >> >> sudo pip install mozdownload >> >> >> Can you please help me . >> >> Thanks & Regards >> Saket Mehrotra >> _______________________________________________ >> Tutor maillist - Tutor at python.org >> To unsubscribe or change subscription options: >> https://mail.python.org/mailman/listinfo/tutor >> > > From alan.gauld at yahoo.co.uk Wed Aug 1 04:13:07 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 1 Aug 2018 09:13:07 +0100 Subject: [Tutor] SSL Error In-Reply-To: References: Message-ID: On 01/08/18 05:07, Saket Mehrotra wrote: > Hi > > I am also not using any Open SSL package. > I have just added " import requests" in py file. And when I run the module > I get the SSL package error ,not sure why. Then you really need to send the complete error message and the code that generates it - the full function definition at least. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Wed Aug 1 14:58:03 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 1 Aug 2018 19:58:03 +0100 Subject: [Tutor] Any ideas why this woudn't work? In-Reply-To: References: Message-ID: On 01/08/18 14:17, Matthew Polack wrote: > > c:\Python>python crops3.py > Traceback (most recent call last): > ? File "crops3.py", line 30, in > ? ? filemenu.add_command(label="Show", command=self.showImg) > NameError: name 'self' is not defined The problem with cutting and pasting/copying code... self is the name used for the first parameter in a class method definition.? But you have not defined any classes so self does not make sense. In fact once you get past this error you will likely run into others since self will have very strange values compared to the original author's intent. I suspect you might also run into other problems since you use from tkinter import * and from PIL import Image... But tkinter also has an Image class which your PIL one will hide. If you intend to use the tkinter Image rather than the PIL one you will be stuck. If you use the import tkinter as tk approach you will avoid the ambiguity. > > > I can't figure out why his works and mine doesn't.... > > Here is all my code so far...can either of you spot anything wrong? > > Thanks so much if you have a chance to look. OK, But I've also CC'd it to the list since its good to keep the discussion public so other people can benefit (and contribute) too. > > Matt > > > > fromtkinter import* > root =Tk("Crop Calculator") > root.title("Crop Calculator") > root.geometry("640x640+0+0") > fromPIL importImage, ImageTk > defdonothing(): > filewin =Toplevel(root) > button =Button(filewin, text="Do nothing button") > button.pack() > defshowImg(self): > load =Image.open('wheat.jpg') > render =ImageTk.PhotoImage(load) > img =Label(self, image=render) > img.image =render > img.place(x=0, y=0) > defShowTxt(self): > text =Label (self, text='Hey there') > text.pack() > menubar =Menu(root) > filemenu =Menu(menubar, tearoff=0) > filemenu.add_command(label="New", command=donothing) > filemenu.add_command(label="Show", command=self.showImg) > filemenu.add_command(label="Show Text", command=self.showTxt) > filemenu.add_command(label="Save", command=donothing) > filemenu.add_command(label="Save as...", command=donothing) > filemenu.add_command(label="Close", command=donothing) > filemenu.add_separator() > filemenu.add_command(label="Exit", command=root.quit) > menubar.add_cascade(label="File", menu=filemenu) > editmenu =Menu(menubar, tearoff=0) > editmenu.add_command(label="Undo", command=donothing) > editmenu.add_separator() > editmenu.add_command(label="Cut", command=donothing) > editmenu.add_command(label="Copy", command=donothing) > editmenu.add_command(label="Paste", command=donothing) > editmenu.add_command(label="Delete", command=donothing) > editmenu.add_command(label="Select All", command=donothing) > menubar.add_cascade(label="Edit", menu=editmenu) > helpmenu =Menu(menubar, tearoff=0) > helpmenu.add_command(label="Help Index", command=donothing) > helpmenu.add_command(label="About...", command=donothing) > menubar.add_cascade(label="Help", menu=helpmenu) > root.config(menu=menubar) > # abutton = Button(root, text="Crop Prices in Australia") > #Main Heading Labels > #Answerlabel > answerlabel=Label(root, text="wheatwords") > # abutton.pack(side='left', fill='both', expand=True) > ''' > instruction.grid(row=1, columnspan=12, sticky='ew') > blanklabel.grid(row=2, columnspan=12, sticky='ew') > blanklabel2.grid(row=11, columnspan=12, sticky='ew') > ''' > wheatcost =("$5.23") > peascost =("$3.23") > lupenscost =("$8.23") > barleycost =("$2.53") > canolacost =("$9.72") > sorghumcost =("$22.23") > #List of Crops > croplabel =Label(root, text="Crop Prices in Australia", fg="white", > bg="green", font=("arial", 36, "bold")) > instruction =Label(root, text="Please select from the following > crops", fg="green", bg="white", font=("arial", 18, "bold")) > wheatbutton =Button(root, text="Wheat", fg="black", bg="yellow") > wheatprice =Label(root, text=wheatcost, fg="white", bg="black") > peasbutton =Button(root, text="Peas", fg="white", bg="green") > peasprice =Label(root, text=peascost, fg="white", bg="black") > lupensbutton =Button(root, text="Lupens", fg="white", bg="brown") > lupensprice =Label(root, text=lupenscost, fg="white", bg="black") > barleybutton =Button(root, text="Barley", fg="white", bg="brown") > barleyprice =Label(root, text=barleycost, fg="white", bg="black") > canolabutton =Button(root, text="Canola", fg="white", bg="red") > canolaprice =Label(root, text=canolacost, fg="white", bg="black") > sorghumbutton =Button(root, text="Sorghum", fg="black", bg="ivory3") > sorghumprice =Label(root, text=sorghumcost, fg="white", bg="black") > blankline =Label(root, text="", bg="white") > label_1 =Label(root, text="Type of Crop", fg="white", bg="black") > label_2 =Label(root, text="Number of Metric Tonnes", fg="white", > bg="black") > entry1 =Entry(root) > entry2 =Entry(root) > blankline2 =Label(root, text="", bg="white") > statusbar =Label(root, text="Copyright 2018", fg="white", bg="black", > relief='sunken') > wheat_image =Image.open("wheat.jpg") > wheat_photo =ImageTk.PhotoImage(wheat_image) > wheatlabel =Button(root, image=wheat_photo, fg="black", bg="yellow") > # Grid positioning of crops. > croplabel.grid(columnspan=12, sticky='ew') > wheatbutton.grid(row=4, column=1, sticky='ew') > wheatprice.grid(row=4, column=2, sticky='ew') > lupensbutton.grid(row=6, column=1, sticky='ew') > lupensprice.grid(row=6, column=2, sticky='ew') > peasbutton.grid(row=4, column=7, sticky='ew') > peasprice.grid(row=4, column=8, sticky='ew') > barleybutton.grid(row=6, column=7, sticky='ew') > barleyprice.grid(row=6, column=8, sticky='ew') > canolabutton.grid(row=8, column=1, sticky='ew') > canolaprice.grid(row=8, column=2, sticky='ew') > sorghumbutton.grid(row=8, column=7, sticky='ew') > sorghumprice.grid(row=8, column=8, sticky='ew') > blankline.grid(row=11, sticky='ew') > label_1.grid(column=1, row=12, sticky=E) > label_2.grid(column=1, row=14, sticky=E) > entry1.grid(column=7, row=12, sticky=E) > entry2.grid(column=7, row=14, sticky=E) > blankline2.grid(row=15, sticky='ew') > statusbar.grid(row=17, columnspan=12, sticky='ew') > name=StringVar() > entry_box =Entry(root, textvariable=name, width=25, bg="Lightblue") > graintype =("porridge") > # Definitions > defrequest(): > price =int(input("What is the current price?")) > amount =int(input("\nHow much grain?")) > defwheatwords(): > print("You have selected to convert "+graintype) > price =int(float(input("What is the current price?"))) > amount =int(input("\nHow much grain in metric tonnes?")) > print("This is") > print(price *amount, "Metric Tonnes") > wheatbutton.configure(command=wheatwords) > defshow_entry_fields(): > print("First Name: %s\nLast Name: %s"%(e1.get(), e2.get())) > master =Tk() > Label(master, text="First Name").grid(row=0) > Label(master, text="Last Name").grid(row=1) > e1 =Entry(master) > e2 =Entry(master) > e1.grid(row=0, column=1) > e2.grid(row=1, column=1) > Button(master, text='Quit', command=master.quit).grid(row=3, column=0, > sticky=W, pady=4) > Button(master, text='Show', command=show_entry_fields).grid(row=3, > column=1, sticky=W, pady=4) > # NEW CODE FROM OTHER > defmy_calculator(amount_mt, price): > print(amount_mt *price) > #nothing happens > defmy_multiply(firstnum, secnum): > print(firstnum *secnum) > #nothing happens > root.mainloop() > > // -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From marc.tompkins at gmail.com Wed Aug 1 19:42:12 2018 From: marc.tompkins at gmail.com (Marc Tompkins) Date: Wed, 1 Aug 2018 16:42:12 -0700 Subject: [Tutor] SSL Error In-Reply-To: References: Message-ID: On Wed, Aug 1, 2018 at 1:13 AM, Alan Gauld via Tutor wrote: > On 01/08/18 05:07, Saket Mehrotra wrote: > > Hi > > > > I am also not using any Open SSL package. > > I have just added " import requests" in py file. And when I run the > module > > I get the SSL package error ,not sure why. > > Then you really need to send the complete error message > and the code that generates it - the full function > definition at least. > THIS. Give us the _whole_ error message, even the parts that look like they don't make any sense. For one thing, the traceback tells us exactly which line of code triggered the exception - and which file that line of code came from. From your description, it sounds like the error is being thrown by the requests module, but we can't tell. I've just taken a look at the source for "requests"; it never asks for PROTOCOL_SSLv23 specifically, so I don't know where that's coming from. PROTOCOL_SSLv23 is a constant in the standard-library ssl module, but not in pyopenssl. (You mentioned that you uninstalled pyopenssl, but requests imports it - so there must be another copy of it on your machine somewhere?) I can't emphasize this enough: the right way to ask questions is also the easiest way - cut and paste. Don't paraphrase, don't edit, don't try to be creative or descriptive. Just give us the entire error message and traceback, and we can go from there. From mehrotra.saket at gmail.com Wed Aug 1 23:46:01 2018 From: mehrotra.saket at gmail.com (Saket Mehrotra) Date: Thu, 2 Aug 2018 09:16:01 +0530 Subject: [Tutor] Tutor Digest, Vol 174, Issue 2 In-Reply-To: References: Message-ID: I am running only one line of code "import requests" Error I am getting is below Traceback (most recent call last): File "/Users/saketmehrotra/Documents/Flaskask.py", line 4, in import requests File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/__init__.py", line 95, in from urllib3.contrib import pyopenssl File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/urllib3/contrib/pyopenssl.py", line 80, in ssl.PROTOCOL_SSLv23: OpenSSL.SSL.SSLv23_METHOD, AttributeError: 'module' object has no attribute 'PROTOCOL_SSLv On Wed, Aug 1, 2018 at 9:30 PM, wrote: > Send Tutor mailing list submissions to > tutor at python.org > > To subscribe or unsubscribe via the World Wide Web, visit > https://mail.python.org/mailman/listinfo/tutor > or, via email, send a message with subject or body 'help' to > tutor-request at python.org > > You can reach the person managing the list at > tutor-owner at python.org > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Tutor digest..." > > Today's Topics: > > 1. Re: SSL Error (Alan Gauld) > > > ---------- Forwarded message ---------- > From: Alan Gauld > To: tutor at python.org > Cc: > Bcc: > Date: Wed, 1 Aug 2018 09:13:07 +0100 > Subject: Re: [Tutor] SSL Error > On 01/08/18 05:07, Saket Mehrotra wrote: > > Hi > > > > I am also not using any Open SSL package. > > I have just added " import requests" in py file. And when I run the > module > > I get the SSL package error ,not sure why. > > Then you really need to send the complete error message > and the code that generates it - the full function > definition at least. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > > > _______________________________________________ > Tutor maillist - Tutor at python.org > https://mail.python.org/mailman/listinfo/tutor > > From rls4jc at gmail.com Wed Aug 1 16:38:03 2018 From: rls4jc at gmail.com (Roger Lea Scherer) Date: Wed, 1 Aug 2018 13:38:03 -0700 Subject: [Tutor] Removing duplicates Message-ID: I'm trying to get a list of tuples to be a float, a numerator, and a denominator for all the fractions: halves, thirds, fourths etc up to ninths. 1/2 returns the same float as 2/4, 3/6, 4/8. I would like to keep only the 1/2. When I try (line 18) to "pop" from the list I get a "TypeError: integer argument expected, got float". When I try (line 18) to "remove" from the list, nothing happens: nothing is removed and I do not receive an error message. What do you think is a good way to solve this? Thank you as always. import math fractions = [(0, 0, 0)] for i in range(1, 10): for j in range(1, 10): if i < j: x = i/j if x not in fractions: fractions.append((x, i, j)) sortedFrac = sorted(fractions) print(sortedFrac) for i in range(len(sortedFrac)): try: if sortedFrac[i][0] == sortedFrac[i-1][0]: # so if the float equals the previous float sortedFrac.pop(sortedFrac[i][0]) # remove the second float else: sortedFrac.append(sortedFrac[i][0]) except ValueError: continue -- Roger Lea Scherer 623.255.7719 *Strengths:* Input, Strategic, Responsibility, Learner, Ideation From oscar.j.benjamin at gmail.com Thu Aug 2 05:34:39 2018 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Thu, 2 Aug 2018 10:34:39 +0100 Subject: [Tutor] Removing duplicates In-Reply-To: References: Message-ID: On 1 August 2018 at 21:38, Roger Lea Scherer wrote: > > I'm trying to get a list of tuples to be a float, a numerator, and a > denominator for all the fractions: halves, thirds, fourths etc up to > ninths. 1/2 returns the same float as 2/4, 3/6, 4/8. I would like to keep > only the 1/2. When I try (line 18) to "pop" from the list I get a "TypeError: > integer argument expected, got float". When I try (line 18) to "remove" > from the list, nothing happens: nothing is removed and I do not receive an > error message. > > What do you think is a good way to solve this? > > Thank you as always. > > import math > > fractions = [(0, 0, 0)] > > for i in range(1, 10): > for j in range(1, 10): > if i < j: > x = i/j > if x not in fractions: > fractions.append((x, i, j)) > sortedFrac = sorted(fractions) > > print(sortedFrac) > > for i in range(len(sortedFrac)): > try: > if sortedFrac[i][0] == sortedFrac[i-1][0]: # so if the float equals > the previous float > sortedFrac.pop(sortedFrac[i][0]) # remove the second > float > else: > sortedFrac.append(sortedFrac[i][0]) > except ValueError: > continue Comparing floats for equality can be flakey. Sometimes two floats that should be equal will not compare equal e.g.: >>> 0.01 + 0.1 - 0.1 == 0.01 False This happens in this case because of intermediate rounding errors. I don't think that should affect you since you are doing precisely one floating point operation i/j to calculate each of your floats but unless you have a very solid understanding of binary floating point I would recommend that you shouldn't compare floating point values as in a==b. For this particular problem I would use integer arithmetic or I would use the fractions module. Doing this with integers you should normalise the numerator and denominator by dividing out their GCD. The fractions module takes care of this for you internally. https://docs.python.org/3.7/library/fractions.html Otherwise in general to remove duplicates you would be better of with a set rather than a list. If you only put x in the set and not i and j then the set will automatically take care of duplicates: https://docs.python.org/3.7/tutorial/datastructures.html#sets -- Oscar From __peter__ at web.de Thu Aug 2 08:49:12 2018 From: __peter__ at web.de (Peter Otten) Date: Thu, 02 Aug 2018 14:49:12 +0200 Subject: [Tutor] Removing duplicates References: Message-ID: Oscar Benjamin wrote: > On 1 August 2018 at 21:38, Roger Lea Scherer wrote: >> >> I'm trying to get a list of tuples to be a float, a numerator, and a >> denominator for all the fractions: halves, thirds, fourths etc up to >> ninths. 1/2 returns the same float as 2/4, 3/6, 4/8. I would like to keep >> only the 1/2. When I try (line 18) to "pop" from the list I get a >> "TypeError: >> integer argument expected, got float". When I try (line 18) to "remove" >> from the list, nothing happens: nothing is removed and I do not receive >> an error message. >> >> What do you think is a good way to solve this? >> >> Thank you as always. >> >> import math >> >> fractions = [(0, 0, 0)] >> >> for i in range(1, 10): >> for j in range(1, 10): >> if i < j: >> x = i/j >> if x not in fractions: >> fractions.append((x, i, j)) >> sortedFrac = sorted(fractions) >> >> print(sortedFrac) >> >> for i in range(len(sortedFrac)): >> try: >> if sortedFrac[i][0] == sortedFrac[i-1][0]: # so if the float >> equals >> the previous float >> sortedFrac.pop(sortedFrac[i][0]) # remove the >> second >> float >> else: >> sortedFrac.append(sortedFrac[i][0]) >> except ValueError: >> continue > > Comparing floats for equality can be flakey. Sometimes two floats that > should be equal will not compare equal e.g.: > >>>> 0.01 + 0.1 - 0.1 == 0.01 > False Do you know if there's a way to construct an example where i/k != (n*i)/(n*k) with preferrably small integers i, k, and n? Python's integer division algorithm defeats my naive attempts ;) I had to resort to i/k == i/(k + 1) >>> k = 10**18 >>> 1/k == 1/(k+1) True > This happens in this case because of intermediate rounding errors. I > don't think that should affect you since you are doing precisely one > floating point operation i/j to calculate each of your floats but > unless you have a very solid understanding of binary floating point I > would recommend that you shouldn't compare floating point values as in > a==b. > > For this particular problem I would use integer arithmetic or I would > use the fractions module. Doing this with integers you should > normalise the numerator and denominator by dividing out their GCD. The > fractions module takes care of this for you internally. > https://docs.python.org/3.7/library/fractions.html > > Otherwise in general to remove duplicates you would be better of with > a set rather than a list. If you only put x in the set and not i and j > then the set will automatically take care of duplicates: > https://docs.python.org/3.7/tutorial/datastructures.html#sets And if you want to keep i and j you can use a dict: fractions = {} for i in range(1, 10): for j in range(1, 10): if i < j: x = i/j if x not in fractions: fractions[x] = x, i, j sorted_unique_fractions = sorted(fractions.values()) From sydney.shall at kcl.ac.uk Thu Aug 2 10:29:14 2018 From: sydney.shall at kcl.ac.uk (Shall, Sydney) Date: Thu, 2 Aug 2018 16:29:14 +0200 Subject: [Tutor] try, except syntax Message-ID: MAC OS X 10.13.6 Anaconda python 3.6.5 Anaconda IPython 6.4.0 I am having difficulty in using the try, except form. I copy and paste a minimal program to illustrate my problem. #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Thu Aug? 2 15:41:15 2018 @author: sydney """ uvc = 2 msg = "Bad argument provided, the value of uvc must be a float." try: ??? type(uvc) == float except TypeError as e: ??? print(e, msg) try: ??? 0.0 > uvc < 1.0 except ValueError: ??? print("Bad argument provided. The value of uvc must be " ????? "greater than 0.0 and less than 1.0.") if type(uvc) != float: ??? raise TypeError("Bad argument provided. And this is also old test." ??????????????????? " The value of UVC must be a float. This is old test") if uvc < 0.0 or uvc > 1.0: ??? raise ValueError("Bad argument provided. The value of uvc must be " ???????????????????? "greater than 0.0 and less than 1.0. This is old test") My problem is this. The two, 'if statements' at the end of the little program work as intended. And I have been using them in a larger program for some time and they have been checked regularly and they work as intended. I am now rewriting a class, as recommended by both Alan and Steven, in which I have previously used these formulations. This time, I thought that perhaps it would be more "pythonic" to write them as try, except. But I cannot find the correct format. I have read and reread the books and the documentation, but I am clearly stupid today. Either I do not need this change or I have written the try, except incorrectly. I am sure that I am making an elementary mistake. Will someone please show tell me whether I should use try, except instead of if ... and then what is the correct syntax. Thanks as always. -- _________ Professor Sydney Shall Department of Haematology/Oncology Phone: +(0)2078489200 E-Mail: sydney.shall [Correspondents outside the College should add @kcl.ac.uk] From oscar.j.benjamin at gmail.com Thu Aug 2 13:54:57 2018 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Thu, 2 Aug 2018 18:54:57 +0100 Subject: [Tutor] Removing duplicates In-Reply-To: References: Message-ID: On 2 August 2018 at 13:49, Peter Otten <__peter__ at web.de> wrote: > Oscar Benjamin wrote: >> >> Comparing floats for equality can be flakey. Sometimes two floats that >> should be equal will not compare equal e.g.: >> >>>>> 0.01 + 0.1 - 0.1 == 0.01 >> False > > Do you know if there's a way to construct an example where > > i/k != (n*i)/(n*k) > > with preferrably small integers i, k, and n? There wouldn't be for small integers. The simplest possible way for Python to implement the division is to convert both numerator and denominator to float before dividing with floating point. For integers up to ~10**16 the conversion to float will be exact. IEEE 754 requires that the divisions would always give the same result since it should give the true result correctly rounded: both divisions should give the same result if the true ratio of the floats is the same. Actually looking here: https://github.com/python/cpython/blob/3.7/Objects/longobject.c#L3835 that is exactly what happens for small integers. Also it looks as if the algorithm for large integers is designed to compute the true result correctly rounded as well. As it mentions in the code though "results may be subject to double rounding on x86 machines that operate with the x87 FPU set to 64-bit precision." What that means is that on some 32 bit CPUs that don't have SSE2 you may see results that are rounded differently. So leaving aside older hardware I don't think there will be a case where i/k != (n*i)/(n*k). All the same I prefer not to use floating point for exact calculations and I would always recommend that a beginner think of floating point operations as inexact. > Python's integer division > algorithm defeats my naive attempts ;) I haven't tried to properly understand the code in long_true_divide but it definitely looks like whoever wrote it knew what they were doing :) Cheers, Oscar From oscar.j.benjamin at gmail.com Thu Aug 2 14:57:23 2018 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Thu, 2 Aug 2018 19:57:23 +0100 Subject: [Tutor] try, except syntax In-Reply-To: References: Message-ID: On 2 August 2018 at 15:29, Shall, Sydney wrote: > > try: > type(uvc) == float > except TypeError as e: > print(e, msg) Let's try this interactively: >>> uvc = 2 >>> type(uvc) >>> type(uvc) == float False So calling type(uvc) doesn't raise an error. It returns the type "int". You then compare this with the type "float" and they are not equal so the comparison results in False. No exception is raised by this code because there hasn't been an error anywhere. If no exception is raised then you cannot catch an exception with try/except. You should use try/except around some code that would raise an exception if given the wrong sort of input e.g.: numstring = input('Enter a number') try: number = int(numstring) except ValueError: print('Not a decimal number: %r' % numstring) In your case do you even need to do this type check? If you're catching the exception then you could also just not catch the exception so that the user sees the error message. The answer to this depends on what kind of user you have. If a user isn't directly touching the code then it shouldn't be possible for them to change the type of uvc so this exception won't occur and you don't need to check for it. If the user is both editing and running the code (e.g. if you are the only user) then it's usually okay to let them see the normal error message that Python will print out so again you don't need to check for it. On the other hand if the user does something that won't *already* lead to an exception but would result in your code doing something meaningless (such as giving a negative number) then that is a good time for you to check something and raise an exception yourself. -- Oscar From marc.tompkins at gmail.com Thu Aug 2 15:19:41 2018 From: marc.tompkins at gmail.com (Marc Tompkins) Date: Thu, 2 Aug 2018 12:19:41 -0700 Subject: [Tutor] try, except syntax In-Reply-To: References: Message-ID: try... except is meant to catch errors: places where your program would otherwise crash. It does NOT work as a truth check. In your example: > try: > type(uvc) == float > except TypeError as e: > print(e, msg) > > "type(uvc)==float" resolves to a standalone True or False, not an exception. What you want in that case is an assertion: > try: > assert type(uvc)==float > except AssertionError as e: > print(e, msg) An assertion says "The following statement is True. If it isn't, I'm going to throw an exception." They're especially useful when writing tests, and should be part of your flow-control toolbox. In your last two examples, > if type(uvc) != float: > raise TypeError("Bad argument provided. And this is also old test." > " The value of UVC must be a float. This is old test") > if uvc < 0.0 or uvc > 1.0: > raise ValueError("Bad argument provided. The value of uvc must be " > "greater than 0.0 and less than 1.0. This is old > test") I assume you must either already be using try/except, or else never getting incorrect input; if you raise an exception but don't catch it, the program terminates. I would wrap those thusly: > try: > if type(uvc) != float: > raise TypeError("Bad argument provided. And this is also old test." > " The value of UVC must be a float. This is old > test") > if uvc < 0.0 or uvc > 1.0: > raise ValueError("Bad argument provided. The value of uvc must be " > "greater than 0.0 and less than 1.0. This is old > test") > except Error as e: > print(e,msg) Generally, however, my approach is to use if/then for normal program flow, and wrap those in try/except for cases where e.g. user error may cause crashes. From adeadmarshal at gmail.com Thu Aug 2 16:12:55 2018 From: adeadmarshal at gmail.com (Ali M) Date: Fri, 3 Aug 2018 00:42:55 +0430 Subject: [Tutor] Getting current listbox item index and bind it to button (Tkinter) Message-ID: Hi, in my code i have the curselection in my enter_meaning function, and it works well and prints the result which comes from db to the text widget. When user searches in entrybox the list lowers down to 1 item, how can i get the index of that item and bind it to the button so it will print the result like curselection does but with pressing the Enter key on keyboard? I tried writing the search_word function and binded it to the button, but it doesn't work, please help i'm still a beginner. import sqlite3 as sqlite import tkinter as tk from tkinter import ttk # GUI Widgets class EsperantoDict: def __init__(self, master): master.title("EsperantoDict") master.iconbitmap("Esperanto.ico") master.resizable(False, False) master.configure(background='#EAFFCD') self.style = ttk.Style() self.search_var = tk.StringVar() self.search_var.trace("w", lambda name, index, mode: self.update_list()) self.style = ttk.Style() self.style.configure("TFrame", background='#EAFFCD') self.style.configure("TButton", background='#C6FF02') self.style.configure("TLabel", background='#EAFFCD') self.frame_header = ttk.Frame(master, relief=tk.FLAT) self.frame_header.config(style="TFrame") self.frame_header.pack(side=tk.TOP, padx=5, pady=5) self.logo = tk.PhotoImage(file=r'C:\EsperantoDict\eo.png') self.small_logo = self.logo.subsample(10, 10) ttk.Label(self.frame_header, image=self.small_logo).grid(row=0, column=0, stick="ne", padx=5, pady=5, rowspan=2) ttk.Label(self.frame_header, text='EsperantoDict', font=('Arial', 18, 'bold')).grid(row=0, column=1) self.frame_content = ttk.Frame(master) self.frame_content.config(style="TFrame") self.frame_content.pack() self.entry_search = ttk.Entry(self.frame_content, textvariable=self.search_var, width=30) self.entry_search.bind('', self.entry_delete) self.entry_search.bind('', self.entry_insert) self.entry_search.grid(row=0, column=0, padx=5) self.entry_search.focus() self.entry_search.bind("", self.edit_input) self.button_search = ttk.Button(self.frame_content, text="Search") self.photo_search = tk.PhotoImage(file=r'C:\EsperantoDict\search.png') self.small_photo_search = self.photo_search.subsample(3, 3) self.button_search.config(image=self.small_photo_search, compound=tk.LEFT, style="TButton") self.button_search.grid(row=0, column=2, columnspan=1, sticky='nw', padx=5) self.button_search.bind('', self.search_word) self.listbox = tk.Listbox(self.frame_content, height=30, width=30) self.listbox.grid(row=1, column=0, padx=5) self.scrollbar = ttk.Scrollbar(self.frame_content, orient=tk.VERTICAL, command=self.listbox.yview) self.scrollbar.grid(row=1, column=1, sticky='nsw') self.listbox.config(yscrollcommand=self.scrollbar.set) self.listbox.bind('<>', self.enter_meaning) self.textbox = tk.Text(self.frame_content, relief=tk.GROOVE, width=60, height=30, borderwidth=2) self.textbox.config(wrap='word') self.textbox.grid(row=1, column=2, sticky='w', padx=5) # SQLite self.db = sqlite.connect(r'C:\EsperantoDict\test.db') self.cur = self.db.cursor() self.cur.execute("SELECT Esperanto FROM Words ORDER BY Esperanto") for row in self.cur: self.listbox.insert(tk.END, row) self.update_list() def update_list(self): self.listbox.delete(0, tk.END) search_term = self.search_var.get().lower() if search_term == 'type to search': search_term = '' self.cur.execute("SELECT Esperanto FROM Words WHERE LOWER(Esperanto) LIKE ? ORDER BY Esperanto", ('%'+search_term+'%',)) for row in self.cur: item = row[0] self.listbox.insert(tk.END, item) for row in range(0, self.listbox.size(), 2): self.listbox.itemconfigure(row, background="#f0f0ff") def edit_input(self, tag): word_to_esp = {'gx': '?', 'cx': '?', 'hx': '?', 'jx': '?', 'ux': '?', 'sx': '?'} user_input = self.entry_search.get() user_input = user_input.lower() for i in word_to_esp: if user_input.__contains__(i): a = user_input.replace(i, word_to_esp[i]) return self.search_var.set(a) # SQLite def enter_meaning(self, tag): for index in self.listbox.curselection(): esperanto = self.listbox.get(index) results = self.cur.execute("SELECT English FROM Words WHERE Esperanto = ?", (esperanto,)) for row in results: self.textbox.delete(1.0, tk.END) self.textbox.insert(tk.END, row[0]) def entry_delete(self, tag): if self.entry_search.get(): self.entry_search.delete(0, tk.END) self.textbox.delete(1.0, tk.END) return None def entry_insert(self, tag): if self.entry_search.get() == '': self.entry_search.insert(0, "Type to Search") return None def search_word(self, tag): esperanto = self.listbox.selection_set(0) results = self.cur.execute("SELECT English FROM Words WHERE Esperanto = ?", (esperanto,)) for row in results: self.textbox.delete(1.0, tk.END) self.textbox.insert(tk.END, row[0]) def main(): root = tk.Tk() EsperantoDict(root) root.mainloop() if __name__ == '__main__': main() # db tbl name: Words # db first field name: Esperanto # db second field name: English From alan.gauld at yahoo.co.uk Thu Aug 2 18:40:48 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 2 Aug 2018 23:40:48 +0100 Subject: [Tutor] Getting current listbox item index and bind it to button (Tkinter) In-Reply-To: References: Message-ID: On 02/08/18 21:12, Ali M wrote: > I tried writing the search_word function and binded it to the button, but > it doesn't work, please help i'm still a beginner. > > def search_word(self, tag): > esperanto = self.listbox.selection_set(0) > results = self.cur.execute("SELECT English FROM Words WHERE > Esperanto = ?", (esperanto,)) > for row in results: > self.textbox.delete(1.0, tk.END) > self.textbox.insert(tk.END, row[0]) The last bit looks suspicious. You delete the contents of textbox each time round the loop. Surely you only want to delete it once before the loop? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Thu Aug 2 18:57:27 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 2 Aug 2018 23:57:27 +0100 Subject: [Tutor] try, except syntax In-Reply-To: References: Message-ID: On 02/08/18 15:29, Shall, Sydney wrote: > uvc = 2 > msg = "Bad argument provided, the value of uvc must be a float." > > try: > ??? type(uvc) == float > except TypeError as e: > ??? print(e, msg) The try block contains an expression that will always evaluate to True or False and thus never raise an exception. Since the expression is never stored or used(in an if or while say) the block does nothing useful. > try: > ??? 0.0 > uvc < 1.0 > except ValueError: > ??? print("Bad argument provided. The value of uvc must be " > ????? "greater than 0.0 and less than 1.0.") This also has an expression but it will never generate a ValueError since its only testing if uvc is between the two values. Again it will either be True or False provided the value of uvc is of a numeric type.... If not it will generate a TypeError. So rather than testing for a ValueError which will never happen, you should be testing for a TypeError. Exceptions are about handling the unexpected, not about managing flow control in your normal execution path. > if type(uvc) != float: > ??? raise TypeError("Bad argument provided. And this is also old test." > ??????????????????? " The value of UVC must be a float. This is old test") Raising the error is fine but it will cause your program to stop. Is that what you want? But mostly in Python we don't check types before using them we use TypeError to catch the mistake when it happens. we are not using try/except to look for wrong types, we just catch the error if it occurs. Mostly we hope it won't. try: your expected normal code here except SomeError catch anything that you hope won't happen but might. > I am now rewriting a class, as recommended by both Alan and Steven, in > which I have previously used these formulations. > > today. Either I do not need this change or I have written the try, > except incorrectly. I am sure that I am making an elementary mistake. Maybe both. If you really do need to do the checks as part of your normal logic then continue using the if style. But if you just think there's a possibility of a wrong value/type being passed then write your code as if there were no errors but wrap it in a try/except block. But only if you can actually do something when the error occurs, otherwise you might as well let Python deal with it and print a traceback. The key thing about try/except is that you should be able to delete it and your code (ie. the try block) should carry on working albeit with an occasional traceback when an error occurs. The traceback tells you which errors you can catch, but they are only worth catching if you can do something about them. (Which might include logging them or printing a more friendly message before exiting) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Thu Aug 2 19:54:11 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 3 Aug 2018 09:54:11 +1000 Subject: [Tutor] try, except syntax In-Reply-To: References: Message-ID: <20180802235410.GL22431@ando.pearwood.info> On Thu, Aug 02, 2018 at 12:19:41PM -0700, Marc Tompkins wrote: > What you want in that case is an assertion: > > try: > assert type(uvc)==float > except AssertionError as e: > print(e, msg) > > An assertion says "The following statement is True. If it isn't, I'm going > to throw an exception." They're especially useful when writing tests, and > should be part of your flow-control toolbox. Absolutely not! Sorry Marc, but that's *terrible* advice (sorry I don't have the delicacy to sugar coat that this morning, I've been railing against the misuse of assert for what sometimes seems like a thousand years...), it is a misuse of assert and buggy as well. https://import-that.dreamwidth.org/676.html -- Steve From carroll at tjc.com Thu Aug 2 18:49:12 2018 From: carroll at tjc.com (Terry Carroll) Date: Thu, 2 Aug 2018 18:49:12 -0400 (EDT) Subject: [Tutor] SSL Error In-Reply-To: References: Message-ID: On Wed, 1 Aug 2018, Marc Tompkins wrote: >> On 01/08/18 05:07, Saket Mehrotra wrote: >>> Hi >>> >>> I am also not using any Open SSL package. >>> I have just added " import requests" in py file. And when I run the >> module >>> I get the SSL package error ,not sure why. > Give us the _whole_ error message, even the parts that look like they don't > make any sense. For one thing, the traceback tells us exactly which line > of code triggered the exception - and which file that line of code came > from. From your description, it sounds like the error is being thrown by > the requests module, but we can't tell. Also, before your "import requests" line, include these: import sys print(sys.version) After the "import requests" line, include this: print(requests.__version__) -- Terry Carroll carroll at tjc.com From rafael.knuth at gmail.com Fri Aug 3 07:14:11 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Fri, 3 Aug 2018 13:14:11 +0200 Subject: [Tutor] Counting Items on a List associated w/ Index # Message-ID: Hi there, I wrote a function which is supposed to count the number of items on each index #. For starters, here's a list I created to test the function: properties = ["mansion, modern, swimming_pool" , "mansion, historic, air_conditioning", "penthouse, modern, whirlpool"] # index 0 = property type # index 1 = style # index 2 = feature Here's the function: def feature_counter(input_lst, index, input_str): num_elt = 0 output_lst = [] for row in input_lst: split_row = row.split(",") output_lst.append(split_row) for each in output_lst: if each[index] == input_str: num_elt = num_elt + 1 return num_elt This function returns the correct result when checking index 0: print(feature_counter(properties, 0, "mansion")) >>> 2 Weirdly, it returns the wrong result when checking index 1: print(feature_counter(properties, 1, "modern")) >>> 0 and index 2: print(feature_counter(properties, 2, "swimming_pool")) >>> 0 Can anyone advise what's wrong with my function? Thanks, Rafael From alan.gauld at yahoo.co.uk Fri Aug 3 14:41:39 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 3 Aug 2018 19:41:39 +0100 Subject: [Tutor] Counting Items on a List associated w/ Index # In-Reply-To: References: Message-ID: On 03/08/18 12:14, Rafael Knuth wrote: > I wrote a function which is supposed to count the number of items on > each index #. > For starters, here's a list I created to test the function: > > properties = ["mansion, modern, swimming_pool" , "mansion, historic, > air_conditioning", "penthouse, modern, whirlpool"] Storing multiple fields in a single string is nearly always the wrong thing to do. It would be much easier to work with tuples of three strings. Always try to make your data look as much like what you are trying to model as possible. However... > def feature_counter(input_lst, index, input_str): > num_elt = 0 > output_lst = [] > for row in input_lst: > split_row = row.split(",") By splitting on the comma you leave the prefix space in place for the 2nd and 3rd items. You need to strip() that off before using it. > output_lst.append(split_row) T^his is exactly the pattern that matches a list comprehension so you could write all of the above as: def feature_counter(input_lst, index, input_str): num_elt = 0 output_lst = [row.split(',').strip() for row in input_lst] And you wouldn't need to do it at all if you stored the base data as tuples of strings... > for each in output_lst: > if each[index] == input_str: > num_elt = num_elt + 1 > return num_elt > > This function returns the correct result when checking index 0: > > print(feature_counter(properties, 0, "mansion")) >>>> 2 > > Weirdly, it returns the wrong result when checking index 1: > and index 2: > > print(feature_counter(properties, 2, "swimming_pool")) >>>> 0 That's because of the leading spaces. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From adeadmarshal at gmail.com Sat Aug 4 04:07:14 2018 From: adeadmarshal at gmail.com (Ali M) Date: Sat, 4 Aug 2018 12:37:14 +0430 Subject: [Tutor] Getting current listbox item index and bind it to button (Tkinter) Message-ID: I have taken the delete statement out of the for loop, but still nothing happens when i click the button. i want that button to take the current list item index and do what the curselection does (which is printing the result in text widget). import sqlite3 as sqlite import tkinter as tk from tkinter import ttk class EsperantoDict: def __init__(self, master): master.title("EsperantoDict") master.iconbitmap("Esperanto.ico") master.resizable(False, False) master.configure(background='#EAFFCD') self.style = ttk.Style() self.search_var = tk.StringVar() self.search_var.trace("w", lambda name, index, mode: self.update_list()) self.style = ttk.Style() self.style.configure("TFrame", background='#EAFFCD') self.style.configure("TButton", background='#C6FF02') self.style.configure("TLabel", background='#EAFFCD') self.frame_header = ttk.Frame(master, relief=tk.FLAT) self.frame_header.config(style="TFrame") self.frame_header.pack(side=tk.TOP, padx=5, pady=5) self.logo = tk.PhotoImage(file=r'C:\EsperantoDict\eo.png') self.small_logo = self.logo.subsample(10, 10) ttk.Label(self.frame_header, image=self.small_logo).grid(row=0, column=0, stick="ne", padx=5, pady=5, rowspan=2) ttk.Label(self.frame_header, text='EsperantoDict', font=('Arial', 18, 'bold')).grid(row=0, column=1) self.frame_content = ttk.Frame(master) self.frame_content.config(style="TFrame") self.frame_content.pack() self.entry_search = ttk.Entry(self.frame_content, textvariable=self.search_var, width=30) self.entry_search.bind('', self.entry_delete) self.entry_search.bind('', self.entry_insert) self.entry_search.grid(row=0, column=0, padx=5) self.entry_search.focus() self.entry_search.bind("", self.edit_input) self.button_search = ttk.Button(self.frame_content, text=u"Ser?u") self.photo_search = tk.PhotoImage(file=r'C:\EsperantoDict\search.png') self.small_photo_search = self.photo_search.subsample(3, 3) self.button_search.config(image=self.small_photo_search, compound=tk.LEFT, style="TButton") self.button_search.grid(row=0, column=2, columnspan=1, sticky='nw', padx=5) self.button_search.bind('', self.enter_meaning) self.listbox = tk.Listbox(self.frame_content, height=30, width=30) self.listbox.grid(row=1, column=0, padx=5) self.scrollbar = ttk.Scrollbar(self.frame_content, orient=tk.VERTICAL, command=self.listbox.yview) self.scrollbar.grid(row=1, column=1, sticky='nsw') self.listbox.config(yscrollcommand=self.scrollbar.set) self.listbox.bind('<>', self.enter_meaning) self.textbox = tk.Text(self.frame_content, relief=tk.GROOVE, width=60, height=30, borderwidth=2) self.textbox.config(wrap='word') self.textbox.grid(row=1, column=2, sticky='w', padx=5) # SQLite self.db = sqlite.connect(r'C:\EsperantoDict\test.db') self.cur = self.db.cursor() self.cur.execute("SELECT Esperanto FROM Words ORDER BY Esperanto") for row in self.cur: self.listbox.insert(tk.END, row) self.update_list() def update_list(self): self.listbox.delete(0, tk.END) search_term = self.search_var.get().lower() if search_term == 'type to search': search_term = '' self.cur.execute("SELECT Esperanto FROM Words WHERE LOWER(Esperanto) LIKE ? ORDER BY Esperanto", ('%' + search_term + '%',)) for row in self.cur: item = row[0] self.listbox.insert(tk.END, item) for row in range(0, self.listbox.size(), 2): self.listbox.itemconfigure(row, background="#f0f0ff") def edit_input(self, tag): word_to_esp = {'gx': '?', 'cx': '?', 'hx': '?', 'jx': '?', 'ux': '?', 'sx': '?'} user_input = self.entry_search.get() user_input = user_input.lower() for i in word_to_esp: if user_input.__contains__(i): a = user_input.replace(i, word_to_esp[i]) return self.search_var.set(a) # SQLite def enter_meaning(self, tag): for index in self.listbox.curselection(): esperanto = self.listbox.get(index) global results results = self.cur.execute("SELECT English FROM Words WHERE Esperanto = ?", (esperanto,)) for row in results: self.textbox.delete(1.0, tk.END) self.textbox.insert(tk.END, row[0]) def entry_delete(self, tag): if self.entry_search.get(): self.entry_search.delete(0, tk.END) self.textbox.delete(1.0, tk.END) return None def entry_insert(self, tag): if self.entry_search.get() == '': self.entry_search.insert(0, "Type to Search") return None def search_word(self, tag): esperanto = self.listbox.selection_set(0) results = self.cur.execute("SELECT English FROM Words WHERE Esperanto = ?", (esperanto,)) self.textbox.delete(1.0, tk.END) for row in results: self.textbox.insert(tk.END, row[0]) def main(): root = tk.Tk() EsperantoDict(root) root.mainloop() if __name__ == '__main__': main() From alan.gauld at yahoo.co.uk Sat Aug 4 08:14:58 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 4 Aug 2018 13:14:58 +0100 Subject: [Tutor] Getting current listbox item index and bind it to button (Tkinter) In-Reply-To: References: Message-ID: On 04/08/18 09:07, Ali M wrote: > I have taken the delete statement out of the for loop, but still nothing > happens when i click the button. You never assign the search_word function to a widget either via the command option or via a bind statement. If you don't bind the function to a widget it will never be called. > i want that button to take the current > list item index and do what the curselection does (which is printing the > result in text widget). I'm not sure what you mean. curselection returns a list of indexes of the items currently selected. It doesn't display anything. Even the code where you use it (enter_meaning) only uses it to fetch the Esperanto strings for use in the SQL. Incidentally, you have the same delete bug in that function too. If you have more than one item selected it will only show the last item. > class EsperantoDict: > def __init__(self, master): ... > self.search_var = tk.StringVar() > self.search_var.trace("w", lambda name, index, mode: > self.update_list()) > ... > self.entry_search = ttk.Entry(self.frame_content, > textvariable=self.search_var, width=30) > self.entry_search.bind('', self.entry_delete) > self.entry_search.bind('', self.entry_insert) > self.entry_search.grid(row=0, column=0, padx=5) > self.entry_search.focus() > self.entry_search.bind("", self.edit_input) > > self.button_search = ttk.Button(self.frame_content, text=u"Ser?u") > self.photo_search = > tk.PhotoImage(file=r'C:\EsperantoDict\search.png') > self.small_photo_search = self.photo_search.subsample(3, 3) > self.button_search.config(image=self.small_photo_search, > compound=tk.LEFT, style="TButton") > self.button_search.grid(row=0, column=2, columnspan=1, sticky='nw', > padx=5) > self.button_search.bind('', self.enter_meaning) Is that the function you intended to put there? > self.listbox = tk.Listbox(self.frame_content, height=30, width=30) > self.listbox.grid(row=1, column=0, padx=5) > self.scrollbar = ttk.Scrollbar(self.frame_content, > orient=tk.VERTICAL, command=self.listbox.yview) > self.scrollbar.grid(row=1, column=1, sticky='nsw') > self.listbox.config(yscrollcommand=self.scrollbar.set) > self.listbox.bind('<>', self.enter_meaning) > > self.textbox = tk.Text(self.frame_content, relief=tk.GROOVE, > width=60, height=30, borderwidth=2) > self.textbox.config(wrap='word') > self.textbox.grid(row=1, column=2, sticky='w', padx=5) > > # SQLite > self.db = sqlite.connect(r'C:\EsperantoDict\test.db') > self.cur = self.db.cursor() > self.cur.execute("SELECT Esperanto FROM Words ORDER BY Esperanto") > for row in self.cur: > self.listbox.insert(tk.END, row) > self.update_list() > ... > # SQLite > def enter_meaning(self, tag): > for index in self.listbox.curselection(): > esperanto = self.listbox.get(index) > global results > results = self.cur.execute("SELECT English FROM Words WHERE > Esperanto = ?", (esperanto,)) > for row in results: > self.textbox.delete(1.0, tk.END) > self.textbox.insert(tk.END, row[0]) Note the delete inside the loop. ... > def search_word(self, tag): > esperanto = self.listbox.selection_set(0) > results = self.cur.execute("SELECT English FROM Words WHERE > Esperanto = ?", (esperanto,)) > self.textbox.delete(1.0, tk.END) > for row in results: > self.textbox.insert(tk.END, row[0]) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From adeadmarshal at gmail.com Mon Aug 6 15:50:32 2018 From: adeadmarshal at gmail.com (Ali M) Date: Tue, 7 Aug 2018 00:20:32 +0430 Subject: [Tutor] Getting current listbox item index and bind it to button (Tkinter) Message-ID: If i delete this line "self.textbox.delete(1.0, tk.END)" in my enter_meaning function the listbox items won't lower down to 1 item and i just want 1 item to be shown after user searches the item in entrybox. what i want to do is: when user searches in entrybox, the listbox items lowers down to that searched item only, and when i click on that 1 remaining item, the results from db prints in text widget, i want to be able to also use the button to print it. how can i configure the button for this? i hope i explained clearly. import sqlite3 as sqlite import tkinter as tk from tkinter import ttk # GUI Widgets class EsperantoDict: def __init__(self, master): master.title("EsperantoDict") master.iconbitmap("Esperanto.ico") master.resizable(False, False) master.configure(background='#EAFFCD') self.style = ttk.Style() self.search_var = tk.StringVar() self.search_var.trace("w", lambda name, index, mode: self.update_list()) self.style = ttk.Style() self.style.configure("TFrame", background='#EAFFCD') self.style.configure("TButton", background='#C6FF02') self.style.configure("TLabel", background='#EAFFCD') self.frame_header = ttk.Frame(master, relief=tk.FLAT) self.frame_header.config(style="TFrame") self.frame_header.pack(side=tk.TOP, padx=5, pady=5) self.logo = tk.PhotoImage(file=r'C:\EsperantoDict\eo.png') self.small_logo = self.logo.subsample(10, 10) ttk.Label(self.frame_header, image=self.small_logo).grid(row=0, column=0, stick="ne", padx=5, pady=5, rowspan=2) ttk.Label(self.frame_header, text='EsperantoDict', font=('Arial', 18, 'bold')).grid(row=0, column=1) self.frame_content = ttk.Frame(master) self.frame_content.config(style="TFrame") self.frame_content.pack() self.entry_search = ttk.Entry(self.frame_content, textvariable=self.search_var, width=30) self.entry_search.bind('', self.entry_delete) self.entry_search.bind('', self.entry_insert) self.entry_search.grid(row=0, column=0, padx=5) self.entry_search.focus() self.entry_search.bind("", self.edit_input) self.button_search = ttk.Button(self.frame_content, text=u"Ser?u") self.photo_search = tk.PhotoImage(file=r'C:\EsperantoDict\search.png') self.small_photo_search = self.photo_search.subsample(3, 3) self.button_search.config(image=self.small_photo_search, compound=tk.LEFT, style="TButton") self.button_search.grid(row=0, column=2, columnspan=1, sticky='nw', padx=5) self.button_search.bind('', self.search_word) self.listbox = tk.Listbox(self.frame_content, height=30, width=30) self.listbox.grid(row=1, column=0, padx=5) self.scrollbar = ttk.Scrollbar(self.frame_content, orient=tk.VERTICAL, command=self.listbox.yview) self.scrollbar.grid(row=1, column=1, sticky='nsw') self.listbox.config(yscrollcommand=self.scrollbar.set) self.listbox.bind('<>', self.enter_meaning) self.textbox = tk.Text(self.frame_content, relief=tk.GROOVE, width=60, height=30, borderwidth=2) self.textbox.config(wrap='word') self.textbox.grid(row=1, column=2, sticky='w', padx=5) # SQLite self.db = sqlite.connect(r'C:\EsperantoDict\test.db') self.cur = self.db.cursor() self.cur.execute("SELECT Esperanto FROM Words ORDER BY Esperanto") for row in self.cur: self.listbox.insert(tk.END, row) self.update_list() def update_list(self): self.listbox.delete(0, tk.END) search_term = self.search_var.get().lower() if search_term == 'type to search': search_term = '' self.cur.execute("SELECT Esperanto FROM Words WHERE LOWER(Esperanto) LIKE ? ORDER BY Esperanto", ('%' + search_term + '%',)) for row in self.cur: item = row[0] self.listbox.insert(tk.END, item) for row in range(0, self.listbox.size(), 2): self.listbox.itemconfigure(row, background="#f0f0ff") def edit_input(self, tag): word_to_esp = {'gx': '?', 'cx': '?', 'hx': '?', 'jx': '?', 'ux': '?', 'sx': '?'} user_input = self.entry_search.get() user_input = user_input.lower() for i in word_to_esp: if user_input.__contains__(i): a = user_input.replace(i, word_to_esp[i]) return self.search_var.set(a) # SQLite def enter_meaning(self, tag): for index in self.listbox.curselection(): global esperanto global results esperanto = self.listbox.get(index) results = self.cur.execute("SELECT English FROM Words WHERE Esperanto = ?", (esperanto,)) for row in results: self.textbox.delete(1.0, tk.END) self.textbox.insert(tk.END, row[0]) def entry_delete(self, tag): if self.entry_search.get(): self.entry_search.delete(0, tk.END) self.textbox.delete(1.0, tk.END) return None def entry_insert(self, tag): if self.entry_search.get() == '': self.entry_search.insert(0, "Type to Search") return None def search_word(self, index): self.listbox.curselection() if self.search_var.get() == self.listbox.get(index): self.textbox.delete(1.0, tk.END) for row in results: self.textbox.insert(tk.END, row[0]) def main(): root = tk.Tk() EsperantoDict(root) root.mainloop() if __name__ == '__main__': main() # db tbl name: Words # db first field name: Esperanto # db second field name: English From alan.gauld at yahoo.co.uk Tue Aug 7 05:15:24 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 7 Aug 2018 10:15:24 +0100 Subject: [Tutor] Getting current listbox item index and bind it to button (Tkinter) In-Reply-To: References: Message-ID: On 06/08/18 20:50, Ali M wrote: > If i delete this line "self.textbox.delete(1.0, tk.END)" in my > enter_meaning function the listbox items won't lower down to 1 item and i > just want 1 item to be shown after user searches the item in entrybox. So just display 1 item. What you are currently doing is displaying all the items and then deleting them except for the last item. Instead, just display the last item by using an index of -1. It's a lot less work. > what i want to do is: when user searches in entrybox, the listbox items > lowers down to that searched item only, But what if more than one item is found? Or can that absolutely never happen? Are you sure? Does Esperanto not have the concept of synonyms? > remaining item, the results from db prints in text widget, i want to be > able to also use the button to print it. how can i configure the button for > this? It should simply be a case of binding the same function to both the entry and button. You just need to ensure that you create a function that stands alone to populate the text box. (I'm assuming that when you say print you really mean "display on screen" and not "print on paper"?) In other words your enter_meaning method should be assigned to both events. Looking at your code you never seem to bind any commands to the button, therefore it presumably does nothing. > # SQLite > def enter_meaning(self, tag): > for index in self.listbox.curselection(): > global esperanto > global results > esperanto = self.listbox.get(index) > results = self.cur.execute("SELECT English FROM Words WHERE > Esperanto = ?", (esperanto,)) > for row in results: > self.textbox.delete(1.0, tk.END) > self.textbox.insert(tk.END, row[0]) Replace the first for loop with index = self.listbox.curselection()[-1] esperanto = self.listbox.get(index) results = self.cur.execute("SELECT English FROM Words WHERE Esperanto = ?", (esperanto,)) And replace the last for loop with self.textbox.delete(1,0,tk.END) self.textbox.insert(tk.END, results[-1][0]) It should have the same effect with a lot less processing. To display the first item use 0 as the index rather than -1 in the second "loop". Incidentally, why make esperanto and results global? You only use them inside this function and they are assigned new values each time so you may as well make them local. Also the first loop assumes your user wants you to search based on the last item selected (if more than one). Is that correct? Should it perhaps be the first item? Or all of them? Or should you configure the listbox so that only one item at a time can be selected?(ie selectmode=tk.SINGLE) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From rafael.knuth at gmail.com Tue Aug 7 08:46:52 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Tue, 7 Aug 2018 14:46:52 +0200 Subject: [Tutor] How to write a function which reads files Message-ID: Hi there, I got this here: file_path = "C:\\Users\\...\\MyFile.txt" # path shortened for better readability with open(file_path) as file_object: contents = file_object.read() print(contents) It works. Now I want to convert the code above into a function. This is what I wrote: def FileReader(file_path): with open(file_path) as file_object: contents = file_object.read return contents print(FilePrinter("C:\\Users\\...\\MyFile.txt")) # path shortened for better readability I got this error message: How do I fix my function? Thanks, Rafael From kwpolska at gmail.com Tue Aug 7 09:23:47 2018 From: kwpolska at gmail.com (Chris Warrick) Date: Tue, 7 Aug 2018 15:23:47 +0200 Subject: [Tutor] How to write a function which reads files In-Reply-To: References: Message-ID: On Tue, 7 Aug 2018 at 15:07, Rafael Knuth wrote: > def FileReader(file_path): > with open(file_path) as file_object: > contents = file_object.read > return contents > > print(FilePrinter("C:\\Users\\...\\MyFile.txt")) # path shortened for > better readability > > I got this error message: > > You forgot the parentheses (), and are returning a reference to the function instead of calling it and returning its result. Do this: contents = file_object.read() Also, consider using snake_case instead of PascalCase for your function name, since the latter is typically used for classes, and perhaps call it read_file to better describe it? -- Chris Warrick PGP: 5EAAEA16 From alan.gauld at yahoo.co.uk Tue Aug 7 09:35:54 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 7 Aug 2018 14:35:54 +0100 Subject: [Tutor] How to write a function which reads files In-Reply-To: References: Message-ID: On 07/08/18 13:46, Rafael Knuth wrote: > Now I want to convert the code above into a function. > This is what I wrote: > > def FileReader(file_path): > with open(file_path) as file_object: > contents = file_object.read > return contents > > print(FilePrinter("C:\\Users\\...\\MyFile.txt")) # path shortened for Note that you used a different name here than in your function definition! I'm guessing that's a typo, but its one reason to always cut 'n paste real code into your emails. Also as a matter of style its usual in Python to make function names start with a lower case letter: def myFunction(): or def my_function(): But that's just a community convention. But Chris has answered your original question, you need to add calling parens. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From rafael.knuth at gmail.com Tue Aug 7 09:51:50 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Tue, 7 Aug 2018 15:51:50 +0200 Subject: [Tutor] How to write a function which reads files In-Reply-To: References: Message-ID: > You forgot the parentheses (), and are returning a reference to the > function instead of calling it and returning its result. Do this: > contents = file_object.read() oh, my bad. Thanks! > Also, consider using snake_case instead of PascalCase for your > function name, since the latter is typically used for classes, and > perhaps call it read_file to better describe it? thanks, I wasn't aware of the naming conventions for functions and classes. will bear that in mind! > Note that you used a different name here than in your > function definition! another typo. I made that in my original code already. Thanks, everything works well now! From evuraan at gmail.com Tue Aug 7 17:32:58 2018 From: evuraan at gmail.com (Evuraan) Date: Tue, 7 Aug 2018 14:32:58 -0700 Subject: [Tutor] =?utf-8?q?python3_-_=C2=B0F/=C2=B0C_printing_those_degre?= =?utf-8?q?e_signs?= Message-ID: Greetings! How to print ?F/?C etc in python3? (This works on a WSL): ~$ python3 Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import platform >>> platform.release() '4.4.0-17134-Microsoft' >>> print('\u00b0'+ " F") ? F Elsewhere, it no longer seem to work: $ python3 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import platform >>> platform.release() '4.4.0-21-generic' >>> print('\u00b0'+ " F") Traceback (most recent call last): File "", line 1, in UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in position 0: ordinal not in range(128) How can we print ?F / ?C etc. - that should work everywhere on python3 so I can use the same code? Thanks in advance! From alan.gauld at yahoo.co.uk Tue Aug 7 17:49:16 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 7 Aug 2018 22:49:16 +0100 Subject: [Tutor] =?utf-8?q?python3_-_=C2=B0F/=C2=B0C_printing_those_degre?= =?utf-8?q?e_signs?= In-Reply-To: References: Message-ID: On 07/08/18 22:32, Evuraan wrote: >>>> print('\u00b0'+ " F") > ? F > > Elsewhere, it no longer seem to work: > > $ python3 > Python 3.5.2 (default, Nov 23 2017, 16:37:01) > [GCC 5.4.0 20160609] on linux > Type "help", "copyright", "credits" or "license" for more information. >>>> import platform >>>> platform.release() > '4.4.0-21-generic' >>>> print('\u00b0'+ " F") > Traceback (most recent call last): > File "", line 1, in > UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in > position 0: ordinal not in range(128) To some degree it depends on what you are printing on, it needs to support unicode. Not all terminals do. Secondly it needs to be set to unicode for its character encoding and it appears from the error condition that yours is set to ascii... You could try setting PYTHONIOENCODING="UTF-8" in your OS shell and see if that helps, but I suspect there's a better way to deal with it... PS. You can check the current setting with: >>> import sys >>> sys.stdout.encoding If it says ascii (or anything other than a Unicode setting) then that's almost certainly your problem. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From mats at wichmann.us Tue Aug 7 18:39:08 2018 From: mats at wichmann.us (Mats Wichmann) Date: Tue, 7 Aug 2018 16:39:08 -0600 Subject: [Tutor] How to write a function which reads files In-Reply-To: References: Message-ID: Question is already answered, just wanted to add a mini-note. def FileReader(file_path): with open(file_path) as file_object: contents = file_object.read return contents you /can/ return the read method here, which is what this typo does. And the caller of the function can use it to read, as in: print(FileReader("...path...")()) that is, since FileReader as originally written returns a callable, you can call it. However in this case, since the use of the file context manager (open using "with" statement) does what it's supposed to, the read will fail, and you get: ValueError: I/O operation on closed file. because as soon as the with statement is exited, things are cleaned up. That's what context managers do. That doesn't mean there are not cases when you will want to return a function/method for use elsewhere, it's part of the "Python is powerful because functions are first-class" argument :) From steve at pearwood.info Tue Aug 7 19:41:46 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 8 Aug 2018 09:41:46 +1000 Subject: [Tutor] =?iso-8859-1?q?python3_-_=B0F/=B0C_printing_those_degree?= =?iso-8859-1?q?_signs?= In-Reply-To: References: Message-ID: <20180807234145.GF22431@ando.pearwood.info> On Tue, Aug 07, 2018 at 02:32:58PM -0700, Evuraan wrote: > Greetings! How to print ?F/?C etc in python3? In Python 3, you should be able to do: print('?F/?C') directly. If you can't, your configuration is broken. If you are including this is a .py file, make sure your text editor is set to use UTF-8 as the encoding. > (This works on a WSL): WSL? > ~$ python3 > Python 3.5.2 (default, Nov 17 2016, 17:05:23) > [GCC 5.4.0 20160609] on linux > Type "help", "copyright", "credits" or "license" for more information. > >>> import platform > >>> platform.release() > '4.4.0-17134-Microsoft' Microsoft Linux? > >>> print('\u00b0'+ " F") > ? F You don't need to use escape codes for this, but if you do, try this: print('\u00b0 F') > Elsewhere, it no longer seem to work: > > $ python3 > Python 3.5.2 (default, Nov 23 2017, 16:37:01) > [GCC 5.4.0 20160609] on linux > Type "help", "copyright", "credits" or "license" for more information. > >>> import platform > >>> platform.release() > '4.4.0-21-generic' What is this? OS X (Macinintosh), Windows, Windows with cgwin, Linux, some other Unix? What does os.name return? > >>> print('\u00b0'+ " F") > Traceback (most recent call last): > File "", line 1, in > UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in > position 0: ordinal not in range(128) Until now, I would have said that error is literally impossible in Python 3.5. Unless you have made a copy-and-paste error, and aren't showing us the correct output, I can't imagine how you are getting that error. This is very weird. Hmmm... thinking... what do these return? sys.getdefaultencoding() sys.stdout.encoding -- Steve From evuraan at gmail.com Tue Aug 7 23:43:53 2018 From: evuraan at gmail.com (Evuraan) Date: Tue, 7 Aug 2018 20:43:53 -0700 Subject: [Tutor] =?utf-8?q?python3_-_=C2=B0F/=C2=B0C_printing_those_degre?= =?utf-8?q?e_signs?= In-Reply-To: References: Message-ID: > > You could try setting > > PYTHONIOENCODING="UTF-8" > > in your OS shell and see if that helps, but I suspect > there's a better way to deal with it... > Thank you! That was it! Exporting thusly made it behave: $ export PYTHONIOENCODING="UTF-8" $ python3 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> print('\u00b0'+ "F") ?F >>> I've come across this env variable even before, but overlooked it this time again. Much appreciated! From mindaslab at protonmail.com Wed Aug 8 01:59:33 2018 From: mindaslab at protonmail.com (Karthikeyan A K) Date: Wed, 08 Aug 2018 05:59:33 +0000 Subject: [Tutor] [Promotion] Book for Data Science Aspirants Message-ID: Hello Python people, Two years ago, my profession changed, I had to do data science work. When I started it, I (though I knew Python) found it to be extremely difficult and I had these doubts: What to learn? Where to learn? Am I doing things right? Where can I find a person who would guide me in the right path? Were the questions that arose in my mind. I had no proper guide and it was pain. So I wrote this book "How To Become A Data Scientist" https://www.amazon.com/dp/B07FYVTNX7 , a guide for those who would like to become Data Scientist. I have crystallized two years of my struggle and answers to it in this book. I hope this book would help you. - Karthikeyan A K From steve at pearwood.info Wed Aug 8 10:20:44 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 9 Aug 2018 00:20:44 +1000 Subject: [Tutor] =?iso-8859-1?q?python3_-_=B0F/=B0C_printing_those_degree?= =?iso-8859-1?q?_signs?= In-Reply-To: References: Message-ID: <20180808142044.GH22431@ando.pearwood.info> On Tue, Aug 07, 2018 at 08:43:53PM -0700, Evuraan wrote: > > > > You could try setting > > > > PYTHONIOENCODING="UTF-8" > > > > in your OS shell and see if that helps, but I suspect > > there's a better way to deal with it... > > > > Thank you! That was it! What system are you using that doesn't already have UTF-8 as the default encoding? -- Steve From robertvstepp at gmail.com Wed Aug 8 21:30:08 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 8 Aug 2018 20:30:08 -0500 Subject: [Tutor] How to write a function which reads files In-Reply-To: References: Message-ID: On Tue, Aug 7, 2018 at 9:13 AM Rafael Knuth wrote: > Alan Gauld wrote: > > Also, consider using snake_case instead of PascalCase for your > > function name, since the latter is typically used for classes, and > > perhaps call it read_file to better describe it? > > thanks, I wasn't aware of the naming conventions for functions and classes. > will bear that in mind! Have you had a look at PEP 8 yet? It covers most of the Python stylistic conventions, particularly if you intend to contribute to Python and its standard libraries. It may be found at: https://www.python.org/dev/peps/pep-0008/ -- boB From robertvstepp at gmail.com Wed Aug 8 21:53:55 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 8 Aug 2018 20:53:55 -0500 Subject: [Tutor] How to write a function which reads files In-Reply-To: References: Message-ID: On Wed, Aug 8, 2018 at 8:30 PM boB Stepp wrote: > > On Tue, Aug 7, 2018 at 9:13 AM Rafael Knuth wrote: Curses! Sorry, Chris! This should be: > > Chris Warrick wrote: > > > Also, consider using snake_case instead of PascalCase for your > > > function name, since the latter is typically used for classes, and > > > perhaps call it read_file to better describe it? > > > > thanks, I wasn't aware of the naming conventions for functions and classes. > > will bear that in mind! > > Have you had a look at PEP 8 yet? It covers most of the Python > stylistic conventions, particularly if you intend to contribute to > Python and its standard libraries. It may be found at: > https://www.python.org/dev/peps/pep-0008/ -- boB From matthew.polack at htlc.vic.edu.au Thu Aug 9 00:10:00 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Thu, 9 Aug 2018 14:10:00 +1000 Subject: [Tutor] Syntax question Message-ID: Hi, I'm trying to configure a button that prints a variable and calls a function at the same time...but I can't figure out how to get the syntax right...or if this is even possible: print("You have selected to convert "), croptype I've tried various combinations of the above...but can't get it to work...any clues as to what I should do: Thanks, Matt code for this part says; def wheatwords(): print("You have selected to convert "), croptype price = int(float(input("What is the current price?"))) amount = int(input("\n How much grain in metric tonnes?")) print("This is") print(price * amount, "Metric Tonnes") wheatbutton = Button(root, text="Wheat", fg="black", bg="yellow") wheatbutton.configure(croptype="wheat", command=wheatwords) Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From alan.gauld at yahoo.co.uk Thu Aug 9 04:38:22 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 9 Aug 2018 09:38:22 +0100 Subject: [Tutor] Syntax question In-Reply-To: References: Message-ID: On 09/08/18 05:10, Matthew Polack wrote: > I'm trying to configure a button that prints a variable and calls a > function at the same time...but I can't figure out how to get the syntax > right...or if this is even possible: Of couse its possible just wrap it in a higher level function: def newfunc(): print(variable) callFunction() > print("You have selected to convert "), croptype The crop type needs to be inside the parens if you want it printed. That's the syntax error. If you are trying to call a function called croptype then you need to put it on a separate line and lose the , and add parens. > code for this part says; > > def wheatwords(): > print("You have selected to convert "), croptype > price = int(float(input("What is the current price?"))) > amount = int(input("\n How much grain in metric tonnes?")) > print("This is") > print(price * amount, "Metric Tonnes") > I'll assume the lack of indentation is an email formatting issue. Did you post in plain text? > wheatbutton = Button(root, text="Wheat", fg="black", bg="yellow") > wheatbutton.configure(croptype="wheat", command=wheatwords) You set croptype to "wheat" but croptype is not an attribute of Button. You can't just add arbitrary attributes you need to use the ones that the object supports. You can see them by using help(). For example: >>> help(tk.Button) Help on class Button in module tkinter: class Button(Widget) | Button widget. | | Method resolution order: | Button | Widget | BaseWidget | Misc | Pack | Place | Grid | builtins.object | | Methods defined here: | | __init__(self, master=None, cnf={}, **kw) | Construct a button widget with the parent MASTER. | | STANDARD OPTIONS | | activebackground, activeforeground, anchor, | background, bitmap, borderwidth, cursor, | disabledforeground, font, foreground | highlightbackground, highlightcolor, | highlightthickness, image, justify, | padx, pady, relief, repeatdelay, | repeatinterval, takefocus, text, | textvariable, underline, wraplength | | WIDGET-SPECIFIC OPTIONS | | command, compound, default, height, | overrelief, state, width | Shows the valid options available. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From arj.python at gmail.com Thu Aug 9 03:57:19 2018 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Thu, 9 Aug 2018 11:57:19 +0400 Subject: [Tutor] Fwd: Syntax question In-Reply-To: References: Message-ID: missed reply all Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius ---------- Forwarded message --------- From: Abdur-Rahmaan Janhangeer Date: Thu, 9 Aug 2018, 11:56 Subject: Re: [Tutor] Syntax question To: Matthew Polack wheatbutton = Button(root, text="Wheat", fg="black", bg="yellow", command=wheatwords) Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius From cmonge26610 at gmail.com Sat Aug 11 13:48:19 2018 From: cmonge26610 at gmail.com (Carlos Monge) Date: Sat, 11 Aug 2018 12:48:19 -0500 Subject: [Tutor] Need help in learning Python Message-ID: I bought two books to help me learn Python. "Python Crash Course" and "Python for Informatics". I have done all of the basic lessons in "Python Crash Course", but it has two additional sections to help instill what I have learned To do those sections I need to install Pygame and make sure I have 'pip' as well as Matplotlib. I have followed the directions in the book but can't get anything to download so I can use it. For the "Python for Informatics" book I need to have files from the internet load where I have Python so I can manipulate them, but I can't seem to get that to work. Also, I would like to install Ubuntu on a second drive with Python, Idle, C language and its compiler so I can also learn Linux. On the Linux drive, I need to install Kali Linux for a class on Cyber Security. I know this is a lot to ask, but I don't need it all at once. I would appreciate help from someone with experience in downloading all of these things onto a windows computer with a second drive for Ubuntu and all of the other software. Any help is appreciated, and if I find someone with the needed expertise, I will happily subscribe on the Python-Tutor Info Page/ From alan.gauld at yahoo.co.uk Sat Aug 11 19:35:56 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 12 Aug 2018 00:35:56 +0100 Subject: [Tutor] Need help in learning Python In-Reply-To: References: Message-ID: On 11/08/18 18:48, Carlos Monge wrote: > have learned To do those sections I need to install Pygame and make sure I > have 'pip' as well as Matplotlib. If you are using a recent Python (v3.4+) then pip should already be installed. PyGame comes with a Windows installer that should set everything up for you. Matplotlib I don;t know about. I suggest you work on each one individually. Let us know what you try and what results you get. Tell us your OS and Python versions and cut n paste any error messages into your mails. Don;t attempt a second install until the first one succeeds. Start with checking that pip is there (or installing it if not) Then do PyGae Then do Matplotlib > Also, I would like to install Ubuntu on a second drive with Python, > Idle, C language and its compiler so I can also learn Linux. On the Linux > drive, I need to install Kali Linux for a class on Cyber Security. Do you want Ubuntu or Kali - they are separate distros and you can't have both at the same time. Since you need Kali for your course I'd suggest going straight to it. As for Python packages on Linux you should find that your distribution has some kind of package manager or software manager for installing new apps. You should find almost all the Python libraries and tools are available there and you can install them that way. It tends to be easier than using pip etc. > Any help is appreciated, and if I find someone with the needed > expertise, I will happily subscribe on the Python-Tutor Info Page/ That's not how it works. The whole group acts as a virtual tutor. You post questions here and whoever is available/qualified jumps in with the answer. That often means you get multiple (possible different) answers to your question, but the best will usually become apparent quite quickly. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From jgledhill at protonmail.com Sat Aug 11 21:34:10 2018 From: jgledhill at protonmail.com (James Gledhill) Date: Sun, 12 Aug 2018 01:34:10 +0000 Subject: [Tutor] Need help in learning Python In-Reply-To: References: Message-ID: I know this is a python focused mail group, but you asked about Linux so I'll answer. :-) I would strongly recommend that you skip Kali Linux for the next little while. Every tool available on Kali can be obtained on Ubuntu. Kali is not beginner friendly, and while the community is great, honestly it's not the most beginner friendly either. If you don't feel comfortable installing the tools you need for your course on Ubuntu, Kali is going to give you a splitting headache. Stick with Ubuntu, learn python, install the tools as you need them and you will learn so much more. Trust me, it took me years to learn that lesson. :-| -------- Original Message -------- On Aug 11, 2018, 12:48 PM, Carlos Monge wrote: > I bought two books to help me learn Python. "Python Crash Course" and > "Python for Informatics". I have done all of the basic lessons in "Python > Crash Course", but it has two additional sections to help instill what I > have learned To do those sections I need to install Pygame and make sure I > have 'pip' as well as Matplotlib. I have followed the directions in the > book but can't get anything to download so I can use it. > For the "Python for Informatics" book I need to have files from the > internet load where I have Python so I can manipulate them, but I can't > seem to get that to work. > > Also, I would like to install Ubuntu on a second drive with Python, > Idle, C language and its compiler so I can also learn Linux. On the Linux > drive, I need to install Kali Linux for a class on Cyber Security. > I know this is a lot to ask, but I don't need it all at once. I would > appreciate help from someone with experience in downloading all of these > things onto a windows computer with a second drive for Ubuntu and all of > the other software. > Any help is appreciated, and if I find someone with the needed > expertise, I will happily subscribe on the Python-Tutor Info Page/ > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From nathanj9715 at gmail.com Sat Aug 11 19:51:21 2018 From: nathanj9715 at gmail.com (Nathan Johnson) Date: Sat, 11 Aug 2018 18:51:21 -0500 Subject: [Tutor] Argparse Error Message-ID: x64 Based PC Windows 10 Home Version 1803 OS Build 17134.191 Python 3.7.0 x32 Hello I am trying to glitch video files for artistic purposes by using a scrip I found on Reddit (linked below). This is the first time I have tried to use Python and I need some help with an error that I keep getting after I input this first part of the script import argparse parser = argparse.ArgumentParser(description="Shift bytes in a file") parser.add_argument("file", help="input file") parser.add_argument("-o", "--output", help="output file") parser.add_argument("-i", "--interval", help="byte interval", default=1000) parser.add_argument("-s", "--shift", help="size of shift", default=4) parser.add_argument("-k", "--skip", help="size of initial skip offset", default=128) args = parser.parse_args() the error says : error: the following arguments are required: file I am trying to follow a post on Reddit https://www.reddit.com/r/glitch_art/comments/5o7irq/i_compiled_a_compendium_of_corruption_effects_on/ with the script that was provided in the comments https://github.com/v0x76/GlitchTools/blob/master/bytsh.py Any help would be appreciated greatly and thank you for your time. From alan.gauld at yahoo.co.uk Sun Aug 12 03:45:57 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 12 Aug 2018 08:45:57 +0100 Subject: [Tutor] Argparse Error In-Reply-To: References: Message-ID: On 12/08/18 00:51, Nathan Johnson wrote: > Hello I am trying to glitch video files for artistic purposes by using a > scrip I found on Reddit (linked below). This is the first time I have tried > to use Python and I need some help with an error that I keep getting after > I input this first part of the script The error is not with the Python code but with the way you are running the script. > the error says > > : error: the following arguments are required: file It is telling you that you need to provide a file argument. Something like: C:\WINDOWS\PROMPT> python D:\Python\myscript.py D:\Image\myfile.img That's what all the argparse stuff is there for, to ensure that Python can read and understand the arguments that are passed when you run the script. The script as it stands does nothing except check the arguments. It does nothing with those arguments. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From david at graniteweb.com Sun Aug 12 12:29:13 2018 From: david at graniteweb.com (David Rock) Date: Sun, 12 Aug 2018 11:29:13 -0500 Subject: [Tutor] Need help in learning Python In-Reply-To: References: Message-ID: <005C076D-600D-4FDA-B1B6-D706B5CF8005@graniteweb.com> > On Aug 11, 2018, at 20:34, James Gledhill via Tutor wrote: > > I know this is a python focused mail group, but you asked about Linux so I'll answer. :-) > I would strongly recommend that you skip Kali Linux for the next little while. Every tool available on Kali can be obtained on Ubuntu. Kali is not beginner friendly, and while the community is great, honestly it's not the most beginner friendly either. If you don't feel comfortable installing the tools you need for your course on Ubuntu, Kali is going to give you a splitting headache. Stick with Ubuntu, learn python, install the tools as you need them and you will learn so much more. > I will second that, and add if you really NEED Kali, it?s possible to run it as a Live image (eg, off a USB stick); you don?t need to install it to use it. https://docs.kali.org/downloading/kali-linux-live-usb-install Doing it this way, you get better flexibility with having Kali without [potentially] destroying what?s currently on your system through trying to set up a multi-boot environment. Bite of smaller chunks instead of trying to learn everything at once and you will be a lot happier. ? David Rock david at graniteweb.com From mats at wichmann.us Sun Aug 12 12:51:33 2018 From: mats at wichmann.us (Mats Wichmann) Date: Sun, 12 Aug 2018 10:51:33 -0600 Subject: [Tutor] Need help in learning Python In-Reply-To: References: Message-ID: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> > Start with checking that pip is there (or installing it if not) > Then do PyGae > Then do Matplotlib For this, please note that the pip "command" is not in the same directory on Windows as the python it is associated with. If you went through the steps to have Python in your PATH, and that works, then add another entry that is just the same but appends the \Scripts comoponent; OR where your instructions tell you to "pip install foo" at a command prompt do instead "python -m pip install foo" I believe the latter is now the recommended way anyway, because it ensures the pip matches the python in case you have more than one copy installed on your system. For your other questions, you could instead of making dual-boot setup, do some initial experiments with running a Linux virtual environment. Here's one possibility which will give you a ton of Python stuff already set up: https://labs.fedoraproject.org/python-classroom/download/index.html From nathanj9715 at gmail.com Sun Aug 12 11:52:49 2018 From: nathanj9715 at gmail.com (Nathan Johnson) Date: Sun, 12 Aug 2018 10:52:49 -0500 Subject: [Tutor] Argparse Error In-Reply-To: References: Message-ID: Okay so I downloaded and saved the script as a .py file in a folder named Python on the D; Drive, and also moved my video file to a folder in my D: drive with the name Video. I tried using it in Command Prompt, Python, and Python IDLE, but I got the same error saying SyntaxError: unexpected character after line continuation character I know this is probably user error, but I am a complete novice so I need a little more explanation than "provide a file argument" please. I need to know how exactly to implement the file argument you provided. Thank you again and sorry for the misunderstanding. On Sun, Aug 12, 2018 at 2:45 AM, Alan Gauld via Tutor wrote: > On 12/08/18 00:51, Nathan Johnson wrote: > > > Hello I am trying to glitch video files for artistic purposes by using a > > scrip I found on Reddit (linked below). This is the first time I have > tried > > to use Python and I need some help with an error that I keep getting > after > > I input this first part of the script > > The error is not with the Python code but with the way you are > running the script. > > > the error says > > > > : error: the following arguments are required: file > > It is telling you that you need to provide a file argument. > Something like: > > C:\WINDOWS\PROMPT> python D:\Python\myscript.py D:\Image\myfile.img > > That's what all the argparse stuff is there for, to ensure > that Python can read and understand the arguments that > are passed when you run the script. > > The script as it stands does nothing except check the arguments. > It does nothing with those arguments. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From alan.gauld at yahoo.co.uk Sun Aug 12 13:24:51 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 12 Aug 2018 18:24:51 +0100 Subject: [Tutor] Argparse Error In-Reply-To: References: Message-ID: On 12/08/18 16:52, Nathan Johnson wrote: > Okay so I downloaded and saved the script as a .py file in a folder named > Python on the D; Drive, and also moved my video file to a folder in my D: > drive with the name Video. I tried using it in Command Prompt, Python, and > Python IDLE, but I got the same error saying > > SyntaxError: unexpected character after line continuation character This is a Python error. I suspect you only get this when trying to run it from IDLE or inside the Python interpreter. Not from the OS command prompt? Its caused by the \ characters which Python sees as line continuation characters. But you should always send us the complete error message not just the last line. Although it looks like gobbldegook it is actually full of useful data. But for now I suspect this is all irrelevant to your problem. Instead follow the suggestion below... > I know this is probably user error, but I am a complete novice so I need a > little more explanation than "provide a file argument" please. I need to > know how exactly to implement the file argument you provided. An "argument" is just the value that you give to a command. So a file argument is just the path to a file. You need to provide that when you execute the command. That's what I was showing you here: >> C:\WINDOWS\PROMPT> python D:\Python\myscript.py D:\Image\myfile.img It says: Use the Windows CMD prompt and Type python followed by the path to your script file followed by the path to your image/video file The last bit (or lack of) is what will generate the file error. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cmonge26610 at gmail.com Sun Aug 12 13:56:18 2018 From: cmonge26610 at gmail.com (Carlos Monge) Date: Sun, 12 Aug 2018 12:56:18 -0500 Subject: [Tutor] Need help in learning Python In-Reply-To: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> References: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> Message-ID: Thank you all. I will start in small steps. First Pygame and Ubuntu. I will add any errors I get. On Sun, Aug 12, 2018 at 11:51 AM, Mats Wichmann wrote: > > > Start with checking that pip is there (or installing it if not) > > Then do PyGae > > Then do Matplotlib > > For this, please note that the pip "command" is not in the same > directory on Windows as the python it is associated with. If you went > through the steps to have Python in your PATH, and that works, then add > another entry that is just the same but appends the \Scripts comoponent; > OR where your instructions tell you to "pip install foo" at a command > prompt do instead "python -m pip install foo" I believe the latter is > now the recommended way anyway, because it ensures the pip matches the > python in case you have more than one copy installed on your system. > > > For your other questions, you could instead of making dual-boot setup, > do some initial experiments with running a Linux virtual environment. > > Here's one possibility which will give you a ton of Python stuff already > set up: > > https://labs.fedoraproject.org/python-classroom/download/index.html > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From nathanj9715 at gmail.com Sun Aug 12 13:59:11 2018 From: nathanj9715 at gmail.com (Nathan Johnson) Date: Sun, 12 Aug 2018 12:59:11 -0500 Subject: [Tutor] Argparse Error In-Reply-To: References: Message-ID: Here is what comes out when I use the command for each program. Command Prompt: C:\Users\natha> C:\WINDOWS\PROMPT> python D:\Python\bytsh.py D:\Video\test.mp4 'C:\WINDOWS\PROMPT' is not recognized as an internal or external command, operable program or batch file. Python 32x: >>> C:\WINDOWS\PROMPT> python D:\Python\bytsh.py D:\Video\test.mp4 File "", line 1 C:\WINDOWS\PROMPT> python D:\Python\bytsh.py D:\Video\test.mp4 SyntaxError: unexpected character after line continuation character >>> Python IDLE: >>> C:\WINDOWS\PROMPT> python D:\Python\bytsh.py D:\Video\test.mp4 SyntaxError: unexpected character after line continuation character >>> which program should I be running this through? On Sun, Aug 12, 2018 at 12:24 PM, Alan Gauld via Tutor wrote: > On 12/08/18 16:52, Nathan Johnson wrote: > > Okay so I downloaded and saved the script as a .py file in a folder named > > Python on the D; Drive, and also moved my video file to a folder in my D: > > drive with the name Video. I tried using it in Command Prompt, Python, > and > > Python IDLE, but I got the same error saying > > > > SyntaxError: unexpected character after line continuation character > > This is a Python error. I suspect you only get this when trying > to run it from IDLE or inside the Python interpreter. Not from > the OS command prompt? Its caused by the \ characters which > Python sees as line continuation characters. > > But you should always send us the complete error message not > just the last line. Although it looks like gobbldegook it is > actually full of useful data. > > But for now I suspect this is all irrelevant to your problem. > Instead follow the suggestion below... > > > I know this is probably user error, but I am a complete novice so I need > a > > little more explanation than "provide a file argument" please. I need to > > know how exactly to implement the file argument you provided. > > An "argument" is just the value that you give to a command. > So a file argument is just the path to a file. You need to > provide that when you execute the command. > > That's what I was showing you here: > > >> C:\WINDOWS\PROMPT> python D:\Python\myscript.py D:\Image\myfile.img > > It says: > > Use the Windows CMD prompt and > > Type > > python > > followed by > > the path to your script file > > followed by > > the path to your image/video file > > The last bit (or lack of) is what will generate the file error. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From alan.gauld at yahoo.co.uk Sun Aug 12 14:36:27 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 12 Aug 2018 19:36:27 +0100 Subject: [Tutor] Argparse Error In-Reply-To: References: Message-ID: <7f03d422-ef9f-9d3e-323e-a768ad31b4cb@yahoo.co.uk> On 12/08/18 18:59, Nathan Johnson wrote: > Here is what comes out when I use the command for each program. > > Command Prompt: > C:\Users\natha> C:\WINDOWS\PROMPT> python D:\Python\bytsh.py > D:\Video\test.mp4 > 'C:\WINDOWS\PROMPT' is not recognized as an internal or external command, > operable program or batch file. Ah, OK. The problem here is that in your case the Windows Prompt is: C:\Users\natha> So don't type the "C:\Windows\prompt>" bit, that is just illustrative to show it is a Windows prompt. (I don't know how your PC is set up so can't predict what the Windows Prompt looks like on your PC, so I used a generic prompt.) So you type: python D:\Python\bytsh.py D:\Video\test.mp4 at the C:\Users\natha> prompt. Hopefully that should work with no errors messages. However, it will not do anything to your file. You will need more python code to do that. Presumably from the same place that you found the current script? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Sun Aug 12 20:36:16 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 13 Aug 2018 10:36:16 +1000 Subject: [Tutor] Argparse Error In-Reply-To: References: Message-ID: <20180813003615.GO22431@ando.pearwood.info> Hi Nathan, Let's talk about the process of debugging a technical problem and the sort of reasoning you might go through to solve these kinds of problems yourself. I know it all seems terribly mysterious and confusing right now, but as you learn to recognise what is going on, it becomes easier. You wrote: > Here is what comes out when I use the command for each program. > > Command Prompt: > C:\Users\natha> C:\WINDOWS\PROMPT> python D:\Python\bytsh.py > D:\Video\test.mp4 > 'C:\WINDOWS\PROMPT' is not recognized as an internal or external command, > operable program or batch file. Here you are actually on the right track, you just didn't realise it. The part "C:\Users\natha>" that displays at the beginning of each line is called the command prompt, or prompt. Unfortunately everyone's prompt is different. For example, here is mine: [steve at ando ~]$ But once you learn to recognise the various forms of prompts, and know not to retype them from examples, things start getting easier. This is what Alan wrote: C:\WINDOWS\PROMPT> Can you see the similarity between his generic placeholder prompt and your actual prompt? Both start with "C:\" and end with ">". When you tried running Alan's example, you got this error message: 'C:\WINDOWS\PROMPT' is not recognized ... So the reasoning process a more experienced user might be: 1. The command prompt looks like C:\...> 2. Alan wrote something that looks like C:\...> 3. Which the Windows shell didn't recognise as a command Conclusion: Maybe the part of what Alan wrote that looks like the command prompt was meant to be a placeholder for the real command prompt? In that case I shouldn't type it as part of the command. I should try again using: python D:\Python\bytsh.py D:\Video\test.mp4 after the real prompt, and see what happens next. "What happens next" is, unfortunately, not necessarily that the bytsh.py program runs correctly and does what you expect. There could be all sorts of errors that occur: - problems with the command (maybe Windows can't find "python"); - misspellings of the script name (did you mean "bytsh" or "bytes"?); - bugs in the script (we still don't know if it works...); - maybe even (but VERY unlikely) you discover a bug in Python. Welcome to the joys of programming! But each problem and error message you get, and solve, puts you one step closer to getting it working correctly. Right now you might be feeling frustrated by these cryptic error messages, but I can tell you: - it gets better with practice and experience; - most error messages actually aren't that cryptic once you learn the jargon and know how to read them; - and honestly, error messages are the programmer's best friend in the world. If you think its bad to be presented with an error message, that's nothing compared to the frustration of being presented with a program or command that does nothing, in total silence. (At least an error message gives you a handle to grab hold of and a way to investigate the problem. Silence gives you... nothing.) Moving on to the next case: > Python 32x: > >>> C:\WINDOWS\PROMPT> python D:\Python\bytsh.py D:\Video\test.mp4 > File "", line 1 > C:\WINDOWS\PROMPT> python D:\Python\bytsh.py D:\Video\test.mp4 > > SyntaxError: unexpected character after line continuation character I'll admit this one is pretty cryptic even to me, I had to think about it to understand what it is complaining about. But the details actually aren't important. The important part is SyntaxError which tells you that this isn't even a line of valid Python code. The Python interpreter is expecting commands written in Python, and you've given it something which it cannot work out how to interpret. (It doesn't follow the rules of Python syntax.) SyntaxError here strongly hints that you shouldn't be using this command at the Python command prompt >>> (and in fact, this is the case). Hopefully you are now one step closer to being able to read these error messages for yourself. Good luck! -- Steve From walliss at metrofibre.co.za Mon Aug 13 02:46:41 2018 From: walliss at metrofibre.co.za (Wallis Short) Date: Mon, 13 Aug 2018 08:46:41 +0200 Subject: [Tutor] Need help in learning Python In-Reply-To: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> References: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> Message-ID: I am also from a Linux background and I second exactly what James and David said. To learn Ubuntu, I would recommend installing Windows Subsystem for Linux onto your existing Windows 10 setup and then get the Ubuntu (or SUSE and Debian) from the Microsoft store and install. It does have a few limitations (especially on the GUI) but again which proper Linux Sysadmin uses the GUI :) Its quite simple to install as you add it via the "Windows Features" and click on "Windows Subsystem for Linux" This is an easy way to have Linux at your beck and call just by invoking the OS by typing a command into the run command cmd Unless of course you don't mind dual booting your laptop or have another laptop/PC close by :) Cheers *Wallis Short* Senior Network Engineer Metro Fibre Networx (Pty) Ltd www.metrofibre.co.za 298 Witch-Hazel Ave, Highveld, Centurion, Gauteng, 0157 South Africa On 12 August 2018 at 18:51, Mats Wichmann wrote: > > > Start with checking that pip is there (or installing it if not) > > Then do PyGae > > Then do Matplotlib > > For this, please note that the pip "command" is not in the same > directory on Windows as the python it is associated with. If you went > through the steps to have Python in your PATH, and that works, then add > another entry that is just the same but appends the \Scripts comoponent; > OR where your instructions tell you to "pip install foo" at a command > prompt do instead "python -m pip install foo" I believe the latter is > now the recommended way anyway, because it ensures the pip matches the > python in case you have more than one copy installed on your system. > > > For your other questions, you could instead of making dual-boot setup, > do some initial experiments with running a Linux virtual environment. > > Here's one possibility which will give you a ton of Python stuff already > set up: > > https://labs.fedoraproject.org/python-classroom/download/index.html > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From gautam.satya.desai at gmail.com Sun Aug 12 22:55:44 2018 From: gautam.satya.desai at gmail.com (Gautam Desai) Date: Sun, 12 Aug 2018 22:55:44 -0400 Subject: [Tutor] Counting the # of iterations OR storing # values in a list Message-ID: Good evening, I am currently working with the lattice.py code attached. The code is a simulation that models the interactions between bacteria by producing a lattice output. Once you run the code, there should be both blue and red bacteria that show on a lattice. I can manipulate the size of the lattice to be an integer. In this case, I have set it to 250 However, there are different bacteria cells occupying each "pixel" on the lattice. I could count the number of red or blue bacteria on the output, but with a size of 250 that would take an extremely long time. I need to keep track of the number of red or blue cells in lists, and while I know how to instantiate a list, I don't know how to store the information I need in the list with the code given. The majority of the code has mostly commented out explanations but not entirely. Thank you for your time, From gautam.satya.desai at gmail.com Mon Aug 13 01:15:42 2018 From: gautam.satya.desai at gmail.com (Gautam Desai) Date: Mon, 13 Aug 2018 01:15:42 -0400 Subject: [Tutor] Counting the # of iterations OR storing # values in a list Message-ID: Good evening, I am currently working with the lattice.py code attached. The code is a simulation that models the interactions between bacteria by producing a lattice output. Once you run the code, there should be both blue and red bacteria that show on a lattice. I can manipulate the size of the lattice to be an integer. In this case, I have set it to 250 However, there are different bacteria cells occupying each "pixel" on the lattice. I could count the number of red or blue bacteria on the output, but with a size of 250 that would take an extremely long time. I need to keep track of the number of red or blue cells in lists, and while I know how to instantiate a list, I don't know how to store the information I need in the list with the code given. The majority of the code has mostly commented out explanations but not entirely. Thank you for your time, From alan.gauld at yahoo.co.uk Mon Aug 13 04:02:36 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 13 Aug 2018 09:02:36 +0100 Subject: [Tutor] [OT] Re: Need help in learning Python In-Reply-To: References: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> Message-ID: This thread is getting seriously off topic, but I'm interested so I'm letting it run... :-) On 13/08/18 07:46, Wallis Short wrote: > To learn Ubuntu, I would recommend installing Windows Subsystem for Linux > onto your existing Windows 10 setup and then get the Ubuntu (or SUSE and > Debian) from the Microsoft store and install. It does have a few > limitations (especially on the GUI) but again which proper Linux Sysadmin > uses the GUI :) This is news to me. Can you elaborate a little on what exactly this Linux Subsystem for Windows does? Does it let me run Linux binaries under Windows? And if so how do they show up on screen? This could potentially be very useful for something I'm currently working on... PS. I probably should just google it, but since you appear to have hands on experience... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Mon Aug 13 04:20:53 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 13 Aug 2018 09:20:53 +0100 Subject: [Tutor] Counting the # of iterations OR storing # values in a list In-Reply-To: References: Message-ID: On 13/08/18 06:15, Gautam Desai wrote: > I am currently working with the lattice.py code attached. The server doesn't like attachments so strips them off for security. As a result we can't see the code. Please resend, but paste the code into the body of your message (in plain text to preserve formatting). It would be helpful to also include your OS and Python version. > lattice. I could count the number of red or blue bacteria on the output, > but with a size of 250 that would take an extremely long time. 250 of anything is not very much in computing terms (even if your lattice is 250 cubed its still not unusually big). But I guess it depends on what the data elements look like. > I need to keep track of the number of red or blue cells in lists, and while > I know how to instantiate a list, I don't know how to store the information > I need in the list with the code given. We can't see the code but the most common operation for adding data to a list is the append() method mylist.append(anObject) But we can say more when we see the code. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Mon Aug 13 04:04:49 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 13 Aug 2018 09:04:49 +0100 Subject: [Tutor] Fwd: Re: Argparse Error In-Reply-To: References: Message-ID: <3ed7dacf-11b8-c13a-94f9-f87dfb619dfe@yahoo.co.uk> Forwarding to list since I seem to have messed up the address last time... -------- Forwarded Message -------- Subject: Re: [Tutor] Argparse Error Date: Sun, 12 Aug 2018 23:44:04 +0100 From: Alan Gauld Reply-To: tutor To: Nathan Johnson On 12/08/18 19:58, Nathan Johnson wrote: > Here is the full script that was provided, but I don't know what else > I'm supposed to do with it except save it in the folder on my D: > drive, and run in in the cmd prompt like you said. > OK, It seems as if there are some other arguments that you need to provide. The one causing the issue here is fileout - ie the output filename. Now, its not clear what else needs to be specified, you probably should ask the author. We are not really best qualified to decipher another coders code! But it looks like values for interval, shift and skip are required too - although I've no idea what they mean! What the code does tell us are the options you need to use, so the command should look like: python D:\Python\bytsh.py -o output.mp4 -i ??? -s ??? -k ??? D:\Video\test.mp4 Where you will need to figure out what kind of values to use for the ??? parts. > > import argparse > > > parser = argparse.ArgumentParser(description="Shift bytes in a file") > > parser.add_argument("file", help="input file") > > parser.add_argument("-o", "--output", help="output file") > > parser.add_argument("-i", "--interval", help="byte interval", > default=1000) > > parser.add_argument("-s", "--shift", help="size of shift", default=4) > > parser.add_argument("-k", "--skip", help="size of initial skip > offset", default=128) > > args = parser.parse_args() > > > filein = args.file > > fileout = args.output > > interval = int(args.interval) > > shift = int(args.shift) > > skip = int(args.skip) > > > f = open(filein, "rb") > > out = open(fileout, "w+b") > > > out.write( f.read1(skip) ) > > > while True: > > byte = f.read1(1) > > if byte == b'': > > break > > I suspect the three lines above should be indented under the whilew like this: while True: ??? byte = f.read1(1) ??? if byte == "b": ???????? break But I don't know if any of the lines below should be indented too... The next 3 could be. And maybe they are in the original and its the mail system thats destroyed them? You need to post in plain text for us to accurately see the original indentation levels (which are critically important in Python) > lbfr = f.read(shift) > > rbfr = f.read(interval-shift) > > out.write(lbfr + byte + rbfr) > > > f.close() > > out.close() > > > This is what the cmd prompt says when I type in the new command > > C:\Users\natha> python D:\Python\bytsh.py D:\Video\test.mp4 > Traceback (most recent call last): > ? File "D:\Python\bytsh.py", line 18, in > ??? out = open(fileout, "w+b") > TypeError: expected str, bytes or os.PathLike object, not NoneType > HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From walliss at metrofibre.co.za Mon Aug 13 04:17:00 2018 From: walliss at metrofibre.co.za (Wallis Short) Date: Mon, 13 Aug 2018 10:17:00 +0200 Subject: [Tutor] [OT] Re: Need help in learning Python In-Reply-To: References: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> Message-ID: Hi Alan Have a look here - I could write it but why invent the wheel :) https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/ A quick "How To" to remote ssh into the WSL once installed sudo apt-get install openssh-server sudo vi /etc/ssh/sshd_config PermitRootLogin no PermitRootLogin - we need to change this to no PasswordAuthentication - We need to change this to yes UsePriviledgeSeperation - We need to change this to no Go to end of file (Shift G) insert AllowUsers ubuntu (or whatever name you chose when you installed WSL) bounce the SSH service. sudo service ssh --full-restart *Wallis Short* Senior Network Engineer Metro Fibre Networx (Pty) Ltd www.metrofibre.co.za 298 Witch-Hazel Ave, Highveld, Centurion, Gauteng, 0157 South Africa On 13 August 2018 at 10:02, Alan Gauld via Tutor wrote: > This thread is getting seriously off topic, but I'm > interested so I'm letting it run... :-) > > On 13/08/18 07:46, Wallis Short wrote: > > To learn Ubuntu, I would recommend installing Windows Subsystem for Linux > > onto your existing Windows 10 setup and then get the Ubuntu (or SUSE and > > Debian) from the Microsoft store and install. It does have a few > > limitations (especially on the GUI) but again which proper Linux Sysadmin > > uses the GUI :) > > This is news to me. Can you elaborate a little on what > exactly this Linux Subsystem for Windows does? Does it > let me run Linux binaries under Windows? And if so how > do they show up on screen? > > This could potentially be very useful for something > I'm currently working on... > > PS. I probably should just google it, but since > you appear to have hands on experience... > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From rafael.knuth at gmail.com Mon Aug 13 11:53:46 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Mon, 13 Aug 2018 17:53:46 +0200 Subject: [Tutor] Is there a better way to write my code? Message-ID: I wrote this code below which aims to concatenate strings with their respective string length. I was wondering if there is a shorter, more elegant way to accomplish this task. Thanks! animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] # step one: convert the animal list into a list of lists animals_lol = [] for animal in animals: animal_split = animal.split(",") animals_lol.append(animal_split) # step two: collect the length of each string in a separate list animals_len = [] for animal in animals: animals_len.append(len(animal)) # step three: append the length of each string to the list of lists for a, b in enumerate(animals_lol): b.append(animals_len[a]) print(animals_lol) [['Dog', 3], ['Tiger', 5], ['SuperLion', 9], ['Cow', 3], ['Panda', 5]] From gautam.satya.desai at gmail.com Mon Aug 13 09:29:02 2018 From: gautam.satya.desai at gmail.com (Gautam Desai) Date: Mon, 13 Aug 2018 09:29:02 -0400 Subject: [Tutor] Counting the # of iterations OR storing # values in a list In-Reply-To: References: Message-ID: Thanks Alan Appreciate your help I?ll try that The code is listed here as well I am currently working with the lattice.py code attached. The code is a simulation that models the interactions between bacteria by producing a lattice output. Once you run the code, there should be both blue and red bacteria that show on a lattice. I can manipulate the size of the lattice to be an integer. In this case, I have set it to 250 However, there are different bacteria cells occupying each "pixel" on the lattice. I could count the number of red or blue bacteria on the output, but It would take an extremely long time I need to keep track of the number of red or blue cells in lists, and while I know how to instantiate a list, I don't know how to store the information I need in the list with the code given. The majority of the code has mostly commented out explanations but not entirely. #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Sat Dec 3 10:51:05 2016 """ #%% imports and prep import numpy as np from numpy.random import rand as r from matplotlib import pyplot as plt from collections import defaultdict as d #%% class Lattice(object): def __init__(self,size=100,slider=0,rb=False,redAdvantage=1,blueAdvantage=1,defKillers=False,density=1,numRatio=1,redGrowth=1,blueGrowth=1,deathRate=100000000,antibioticDeath=1): self.rb=rb #rb=True means the lattice contains only red and blue bacteria self.slider=slider #if slider is 0 then only killing happens, if slider is 1 then only "random death" and for a range between it's a mixture #set up growth and killing disparity between red and blue bacteria self.redGrowth=redGrowth #1 means equal growth self.blueGrowth=blueGrowth self.redAdvantage=redAdvantage #killing disparity, 1 means equal killers self.blueAdvantage=blueAdvantage #establish the size of the lattice. For a non-square lattice use size=[x,y] try: x,y=size[1],size[0] except TypeError: x,y=size,size; self.x=x self.y=y self.size=size #if defective killers then red and blue can't kill each other self.defKillers=defKillers #overall cell density at initialization of the lattice self.density=density #overall number ratio (number of blue/ total number of cells) self.numRatio=numRatio #if defective killers set to true then there's no random death either (no killing, no random death) if defKillers==True: self.slider=0; if rb: #initialize the lattice to contain only red and blue cells and empty sites, chosen randomly according to numRatio and density self.lattice=np.random.choice([.2295,.00254],size=(x,y)) try: if density!=1: self.lattice=np.random.choice([0,.2295,.00254],p=[1-density,(density)*(1-numRatio),density*(numRatio)],size=(x,y)) except ValueError: print("Density should be an integer or float") else: #initialize the lattice with a bunch of different types of cells (represented as different colors) self.lattice=r(x,y) if density!=1: for bug in np.ravel(self.lattice): if r()>density: self.lattice[self.lattice==bug]=0 #killdict is a hashtable containing the killing effectiveness for each color killdict=d(list) killdict[0]=0 for color in np.ravel(self.lattice): killdict[color]=r() killdict[0]=0 self.killdict=killdict def evolve(self,n_steps): #main function, moves the lattice forward n steps in time for t in range(n_steps): #pick lattice site try: j=np.random.randint(1,self.y-2) i=np.random.randint(1,self.x-2) except ValueError: #this will happen if you've chosen your lattice to be one dimensional i=0 j=np.random.randint(0,self.y-1) #random death happens if slider>random float in [0,1] if self.slider>r(): self.lattice[i,j]=np.random.choice(np.ravel(self.lattice[i-1:i+2,j-1:j+2])) #else killing/filling a la IBM happens else: #get the neighborhood of the ith,jth 'pixel' neighborhood=self.lattice[i-1:i+2,j-1:j+2]; # find number of species one (red, .2295), species two (blue, .00254) n_blue=np.size(neighborhood[neighborhood==0.00254]); n_red=np.size(neighborhood[neighborhood==.2295]); n_enemy=np.size(neighborhood[neighborhood!=self.lattice[i,j]]); #total number of differently colored cells in neighborhood # KILLING..........########## if (self.rb==True and self.lattice[i,j]==.2295): #site is filled with red bact if self.x==1: #this will happen if your lattice is one dimensional thresh=.5 else: thresh=2 if n_blue*r()*self.blueAdvantage>thresh: #if number of blue cells * their killing advantage * random number > 2, kill this red bacteria (replace with empty site) if self.defKillers==False: self.lattice[i,j]=0; #kill this bacteria elif (self.rb==True and self.lattice[i,j]==.00254): #site is filled with a blue bacteria if self.x==1: thresh=.5 else: thresh=2 if n_red*r()*self.redAdvantage>thresh: if self.defKillers==False: self.lattice[i,j]=0; #kill this bacteria elif (n_enemy>0 and self.lattice[i,j]!=0): #site is not empty and has neighbors (non-specific neighbors, different color) enemy_weight=0; for enemy in np.ravel(neighborhood): if (enemy!=0 and enemy!=self.lattice[i,j]): try: enemy_weight+=self.killdict[enemy]; except TypeError: print("ERROR") pass #enemy_weight=enemy_weight+self.killdict[enemy][0]; if enemy_weight*r()>2: #if enough enemies, kill this bacterium self.lattice[i,j]=0; # FILLING ....... ######### elif (self.lattice[i,j]==0): #site is empty if (self.rb==True and n_red+n_blue>0): #going to fill with either red or blue if (((n_red*self.redGrowth+n_blue*self.blueGrowth)*r())>2): if (n_red*self.redGrowth*r()>n_blue*self.blueGrowth*r()): self.lattice[i,j]=.2295 else: self.lattice[i,j]=0.00254; else: self.lattice[i,j]=0; elif(n_enemy>0): choices=np.ravel(neighborhood[neighborhood!=0]) #find all the other colors in neighborhood if choices.size==0: #if no other cells in neighborhood then stay empty self.lattice[i,j]=0 continue #fill with one of the other colors in neighborhood (according to number of cells) choices=list(choices) choices2=[choice*(1-self.killdict[choice]) for choice in choices] choices2=[choice/len(choices2) for choice in choices2] zeroprob=1-sum(choices2) choices2.append(zeroprob) choices2=np.array(choices2) choices.append(0) choices=np.array(choices) self.lattice[i,j]=np.random.choice(choices,p=choices2) #self.lattice[i,j]=np.random.choice(np.ravel(neighborhood[neighborhood!=0])) return def view(self): #use this to view your lattice def int2color(x): #converts lattice integer to RGB tuple red_val=int(1000*x%255) green_val=int(10000*x%255) blue_val=int(100000*x%255) return (red_val,green_val,blue_val) from PIL import Image lu=list(map(int2color,np.ravel(self.lattice[:,:]))) #now a list of RGB tuples imu = Image.new('RGB', [self.lattice.shape[1],self.lattice.shape[0]]) imrb = Image.new('RGB', [self.lattice.shape[1],self.lattice.shape[0]]) imu.putdata(lu); imu.show if self.rb!=True: return imu return imu my_lattice = Lattice(size=50, slider=0, rb=True, numRatio=20, deathRate=100000) my_lattice.view() im = my_lattice.view(); im.show() On Mon, Aug 13, 2018 at 04:21 Alan Gauld via Tutor wrote: > On 13/08/18 06:15, Gautam Desai wrote: > > > I am currently working with the lattice.py code attached. > > The server doesn't like attachments so strips them off > for security. As a result we can't see the code. > > Please resend, but paste the code into the body of your > message (in plain text to preserve formatting). > It would be helpful to also include your OS and > Python version. > > > lattice. I could count the number of red or blue bacteria on the output, > > but with a size of 250 that would take an extremely long time. > > 250 of anything is not very much in computing terms > (even if your lattice is 250 cubed its still not > unusually big). But I guess it depends on what the data > elements look like. > > > I need to keep track of the number of red or blue cells in lists, and > while > > I know how to instantiate a list, I don't know how to store the > information > > I need in the list with the code given. > > We can't see the code but the most common operation for > adding data to a list is the append() method > > mylist.append(anObject) > > But we can say more when we see the code. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From cmonge26610 at gmail.com Mon Aug 13 14:49:04 2018 From: cmonge26610 at gmail.com (Carlos Monge) Date: Mon, 13 Aug 2018 13:49:04 -0500 Subject: [Tutor] [OT] Re: Need help in learning Python In-Reply-To: References: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> Message-ID: Ok, this may have been a fatal error on my part but I decided to start fresh and uninstalled my old version of Python. Now when I try to reinstall I get these error messages.. Setup failed one or more issues caused the setup to fail. Please fix the issues and then retry setup. For more information see the log file. 0x80070643- Fatal error during installation. I don't understand what the problem is because it is supposedly installing to= C:\Users\cmongeoroplate09\AppData\Local\Programs\Python\Python37-32 I also get another error message that says: The TARGETDIR Variable must be provided when invoking the installer I don't know what's happening. On Mon, Aug 13, 2018 at 3:17 AM, Wallis Short wrote: > Hi Alan > > Have a look here - I could write it but why invent the wheel :) > > https://www.howtogeek.com/249966/how-to-install-and-use- > the-linux-bash-shell-on-windows-10/ > > A quick "How To" to remote ssh into the WSL once installed > sudo apt-get install openssh-server > > sudo vi /etc/ssh/sshd_config > PermitRootLogin no > > PermitRootLogin - we need to change this to no > PasswordAuthentication - We need to change this to yes > UsePriviledgeSeperation - We need to change this to no > > Go to end of file (Shift G) > insert > > AllowUsers ubuntu (or whatever name you chose when you installed WSL) > > bounce the SSH service. > > sudo service ssh --full-restart > > > *Wallis Short* Senior Network Engineer > > > > Metro Fibre Networx (Pty) Ltd > www.metrofibre.co.za > > 298 Witch-Hazel Ave, Highveld, Centurion, Gauteng, 0157 South Africa > +Centurion,+Gauteng,+0157+South+Africa&entry=gmail&source=g> > > > On 13 August 2018 at 10:02, Alan Gauld via Tutor wrote: > > > This thread is getting seriously off topic, but I'm > > interested so I'm letting it run... :-) > > > > On 13/08/18 07:46, Wallis Short wrote: > > > To learn Ubuntu, I would recommend installing Windows Subsystem for > Linux > > > onto your existing Windows 10 setup and then get the Ubuntu (or SUSE > and > > > Debian) from the Microsoft store and install. It does have a few > > > limitations (especially on the GUI) but again which proper Linux > Sysadmin > > > uses the GUI :) > > > > This is news to me. Can you elaborate a little on what > > exactly this Linux Subsystem for Windows does? Does it > > let me run Linux binaries under Windows? And if so how > > do they show up on screen? > > > > This could potentially be very useful for something > > I'm currently working on... > > > > PS. I probably should just google it, but since > > you appear to have hands on experience... > > > > -- > > Alan G > > Author of the Learn to Program web site > > http://www.alan-g.me.uk/ > > http://www.amazon.com/author/alan_gauld > > Follow my photo-blog on Flickr at: > > http://www.flickr.com/photos/alangauldphotos > > > > > > _______________________________________________ > > Tutor maillist - Tutor at python.org > > To unsubscribe or change subscription options: > > https://mail.python.org/mailman/listinfo/tutor > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From david at graniteweb.com Mon Aug 13 15:50:05 2018 From: david at graniteweb.com (David Rock) Date: Mon, 13 Aug 2018 14:50:05 -0500 Subject: [Tutor] [OT] Re: Need help in learning Python In-Reply-To: References: <7ecd1bfd-b3a0-ddf4-b188-23b06a72d9fa@wichmann.us> Message-ID: > On Aug 13, 2018, at 13:49, Carlos Monge wrote: > > Ok, this may have been a fatal error on my part but I decided to start > fresh and uninstalled my old version of Python. Now when I try to reinstall > I get these error messages.. Have you tried rebooting? Maybe you have some lingering cruft in memory. ? David Rock david at graniteweb.com From breamoreboy at gmail.com Mon Aug 13 16:21:22 2018 From: breamoreboy at gmail.com (Mark Lawrence) Date: Mon, 13 Aug 2018 21:21:22 +0100 Subject: [Tutor] Is there a better way to write my code? In-Reply-To: References: Message-ID: On 13/08/18 16:53, Rafael Knuth wrote: > I wrote this code below which aims to concatenate strings with their > respective string length. > I was wondering if there is a shorter, more elegant way to accomplish this task. > Thanks! > > animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] > > # step one: convert the animal list into a list of lists > > animals_lol = [] > > for animal in animals: > animal_split = animal.split(",") > animals_lol.append(animal_split) > > # step two: collect the length of each string in a separate list > > animals_len = [] > > for animal in animals: > animals_len.append(len(animal)) > > # step three: append the length of each string to the list of lists > > for a, b in enumerate(animals_lol): > b.append(animals_len[a]) > > print(animals_lol) > > [['Dog', 3], ['Tiger', 5], ['SuperLion', 9], ['Cow', 3], ['Panda', 5]] > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > For a definition of better:- animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] animals_lol = [] for animal in animals: animals_lol.append((animal, len(animal))) print(animals_lol) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From mats at wichmann.us Mon Aug 13 16:11:12 2018 From: mats at wichmann.us (Mats Wichmann) Date: Mon, 13 Aug 2018 14:11:12 -0600 Subject: [Tutor] Is there a better way to write my code? In-Reply-To: References: Message-ID: On 08/13/2018 09:53 AM, Rafael Knuth wrote: > I wrote this code below which aims to concatenate strings with their > respective string length. did you mean concatenate? because you don't do any concatenation... any time you hear keeping a data element with some information associated, you should be thinking a dictionary data type, though there's nothing wrong with having a data element be a list or a tuple either, and we don't know if you have some specific requirements that are not showing here. > I was wondering if there is a shorter, more elegant way to accomplish this task. > Thanks! > > animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] > > # step one: convert the animal list into a list of lists > > animals_lol = [] > > for animal in animals: > animal_split = animal.split(",") > animals_lol.append(animal_split) > > # step two: collect the length of each string in a separate list > > animals_len = [] > > for animal in animals: > animals_len.append(len(animal)) > > # step three: append the length of each string to the list of lists > > for a, b in enumerate(animals_lol): > b.append(animals_len[a]) > > print(animals_lol) > > [['Dog', 3], ['Tiger', 5], ['SuperLion', 9], ['Cow', 3], ['Panda', 5]] If you want a dictionary, you can try this one-liner: animalinfo = { animal: len(animal) for animal in animals } print(animalinfo) From neilc at norwich.edu Mon Aug 13 16:26:26 2018 From: neilc at norwich.edu (Neil Cerutti) Date: Mon, 13 Aug 2018 20:26:26 +0000 (UTC) Subject: [Tutor] Is there a better way to write my code? References: Message-ID: On 2018-08-13, Rafael Knuth wrote: > I wrote this code below which aims to concatenate strings with their > respective string length. I was wondering if there is a > shorter, more elegant way to accomplish this task. Thanks! > > animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] You can perform the whole operation with a single list comprehension. animals_lol = [[a, len(a)] for a in animals] Which is shorthand for the following loop: animals_lol = [] for a in animals: animals_lol.append([a, len(a)]) -- Neil Cerutti From __peter__ at web.de Mon Aug 13 17:43:43 2018 From: __peter__ at web.de (Peter Otten) Date: Mon, 13 Aug 2018 23:43:43 +0200 Subject: [Tutor] Counting the # of iterations OR storing # values in a list References: Message-ID: Gautam Desai wrote: > I am currently working with the lattice.py code attached. The code is a > simulation that models the interactions between bacteria by producing a > lattice output. > > Once you run the code, there should be both blue and red bacteria that > show > on a lattice. I can manipulate the size of the lattice to be an integer. > In this case, I have set it to 250 > > However, there are different bacteria cells occupying each "pixel" on the > lattice. I could count the number of red or blue bacteria on the output, > but It would take an extremely long time Counting doesn't take very long, at least for *only* 250**2 cells, and there's even a Counter in the stdlib. When I tried $ python3 -i lattice.py >>> from collections import Counter >>> Counter(np.ravel(my_lattice.lattice)) Counter({0.22950000000000001: 31306, 0.0025400000000000002: 31194}) there was no noticeable delay on my aging hardware. For really large arrays >>> (my_lattice.lattice == 0.2295).sum() 31306 is probably faster. From matthew.polack at htlc.vic.edu.au Mon Aug 13 20:31:05 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Tue, 14 Aug 2018 10:31:05 +1000 Subject: [Tutor] Syntax question In-Reply-To: References: Message-ID: Just a quick 'Thank you' for this advice the other day Alan and Abdur-Rahmaan. Greatly appreciated as we work together with our students here. Thank you. Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Thu, Aug 9, 2018 at 6:38 PM, Alan Gauld via Tutor wrote: > On 09/08/18 05:10, Matthew Polack wrote: > > > I'm trying to configure a button that prints a variable and calls a > > function at the same time...but I can't figure out how to get the syntax > > right...or if this is even possible: > Of couse its possible just wrap it in a higher level function: > > def newfunc(): > print(variable) > callFunction() > > > print("You have selected to convert "), croptype > > The crop type needs to be inside the parens > if you want it printed. That's the syntax error. > > If you are trying to call a function called croptype > then you need to put it on a separate line and lose the , > and add parens. > > > > code for this part says; > > > > def wheatwords(): > > print("You have selected to convert "), croptype > > price = int(float(input("What is the current price?"))) > > amount = int(input("\n How much grain in metric tonnes?")) > > print("This is") > > print(price * amount, "Metric Tonnes") > > > > I'll assume the lack of indentation is an email formatting > issue. Did you post in plain text? > > > > wheatbutton = Button(root, text="Wheat", fg="black", bg="yellow") > > wheatbutton.configure(croptype="wheat", command=wheatwords) > > You set croptype to "wheat" but croptype is not an attribute > of Button. You can't just add arbitrary attributes you need > to use the ones that the object supports. You can see them > by using help(). For example: > > >>> help(tk.Button) > > Help on class Button in module tkinter: > > class Button(Widget) > | Button widget. > | > | Method resolution order: > | Button > | Widget > | BaseWidget > | Misc > | Pack > | Place > | Grid > | builtins.object > | > | Methods defined here: > | > | __init__(self, master=None, cnf={}, **kw) > | Construct a button widget with the parent MASTER. > | > | STANDARD OPTIONS > | > | activebackground, activeforeground, anchor, > | background, bitmap, borderwidth, cursor, > | disabledforeground, font, foreground > | highlightbackground, highlightcolor, > | highlightthickness, image, justify, > | padx, pady, relief, repeatdelay, > | repeatinterval, takefocus, text, > | textvariable, underline, wraplength > | > | WIDGET-SPECIFIC OPTIONS > | > | command, compound, default, height, > | overrelief, state, width > | > > Shows the valid options available. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From nmadhok at g.clemson.edu Mon Aug 13 20:54:18 2018 From: nmadhok at g.clemson.edu (Nitin Madhok) Date: Mon, 13 Aug 2018 20:54:18 -0400 Subject: [Tutor] Is there a better way to write my code? In-Reply-To: References: Message-ID: <7E49CA98-11E7-4E05-964D-3768A2F79174@g.clemson.edu> Use List comprehension: animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] animals_lol = [[animal, len(animal)] for animal in animals] print(animals_lol) [['Dog', 3], ['Tiger', 5], ['SuperLion', 9], ['Cow', 3], ['Panda', 5]] If you want to read more about list comprehension, https://www.pythonforbeginners.com/lists/list-comprehensions-in-python/ is a good resource! -- Thanks, Nitin Madhok Clemson University CONFIDENTIALITY NOTICE This e-mail, and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain privileged and/or confidential information. If you are not the intended recipient of this e-mail, any dissemination, distribution or copying of this e-mail, and any attachments thereto, is strictly prohibited. If you have received this e-mail in error, please immediately notify the sender by e-mail or telephone and permanently delete all copies of this e-mail and any attachments. > On Aug 13, 2018, at 11:53 AM, Rafael Knuth wrote: > > I wrote this code below which aims to concatenate strings with their > respective string length. > I was wondering if there is a shorter, more elegant way to accomplish this task. > Thanks! > > animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] > > # step one: convert the animal list into a list of lists > > animals_lol = [] > > for animal in animals: > animal_split = animal.split(",") > animals_lol.append(animal_split) > > # step two: collect the length of each string in a separate list > > animals_len = [] > > for animal in animals: > animals_len.append(len(animal)) > > # step three: append the length of each string to the list of lists > > for a, b in enumerate(animals_lol): > b.append(animals_len[a]) > > print(animals_lol) > > [['Dog', 3], ['Tiger', 5], ['SuperLion', 9], ['Cow', 3], ['Panda', 5]] > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From rafael.knuth at gmail.com Tue Aug 14 02:56:29 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Tue, 14 Aug 2018 08:56:29 +0200 Subject: [Tutor] Is there a better way to write my code? In-Reply-To: References: Message-ID: > I wrote this code below > I was wondering if there is a shorter, more elegant way to accomplish this task. > Thanks! thank you so much everyone! List comprehension is really cool. One thing I like about list comprehension is that you can get a dictionary, tuples or lists as a result by just changing the type of braces. # dictionary colors = ["red", "blue", "white", "yellow"] colors_len = [{color, len(color)} for color in colors] print(colors_len) # tuples colors = ["red", "blue", "white", "yellow"] colors_len = [(color, len(color)) for color in colors] print(colors_len) # lists colors = ["red", "blue", "white", "yellow"] colors_len = [[color, len(color)] for color in colors] print(colors_len) Can you shed some light on when to use which of the above data structures? I assume there is no simple answer to that question, I am still trying to understand the fundamentals of Python (which happens to be my first programming language). Thanks! > animals = ["Dog", "Tiger", "SuperLion", "Cow", "Panda"] > > # step one: convert the animal list into a list of lists > > animals_lol = [] > > for animal in animals: > animal_split = animal.split(",") > animals_lol.append(animal_split) > > # step two: collect the length of each string in a separate list > > animals_len = [] > > for animal in animals: > animals_len.append(len(animal)) > > # step three: append the length of each string to the list of lists > > for a, b in enumerate(animals_lol): > b.append(animals_len[a]) > > print(animals_lol) > > [['Dog', 3], ['Tiger', 5], ['SuperLion', 9], ['Cow', 3], ['Panda', 5]] From alan.gauld at yahoo.co.uk Tue Aug 14 04:03:44 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 14 Aug 2018 09:03:44 +0100 Subject: [Tutor] Is there a better way to write my code? In-Reply-To: References: Message-ID: On 14/08/18 07:56, Rafael Knuth wrote: > List comprehension is really cool. One thing I like about list > comprehension is that you can get a dictionary, tuples or lists as a > result by just changing the type of braces. > > # dictionary > colors = ["red", "blue", "white", "yellow"] > colors_len = [{color, len(color)} for color in colors] > print(colors_len) Actually, these are sets not dictionaries. A dictionary would have pairs separated by a colon, a set just has single values separated by commas. They both use {}. However List comprehensions are a special subset of a more general construct called a generator expression and with those you can build dictionaries: colors = ["red", "blue", "white", "yellow"] colors_len = dict( (color, len(color)) for color in colors] ) print(colors_len) > # tuples > colors = ["red", "blue", "white", "yellow"] > colors_len = [(color, len(color)) for color in colors] > print(colors_len) This gives a list of tuples, but you can use a gen exp to create a tuple of tuples: colors_len = tuple((color, len(color)) for color in colors) > # lists > colors = ["red", "blue", "white", "yellow"] > colors_len = [[color, len(color)] for color in colors] > print(colors_len) So many choices :-) > Can you shed some light on when to use which of the above data structures? > I assume there is no simple answer to that question, Correct, it all depends on the nature of the data and what you plan on doing with it. But there are some general guidelines for collections: - Use a list for objects(*) where you might need to change the value of one of the objects - Use a tuple for objects where you don't need to change the values (it remains the same during the life of the program). - Use a tuple if you want to use the collection as a key in a dictionary. - Use a set where you want to eliminate duplicates - Use a dict where you want direct access to an object based on some unique characeristic. - Use a class where you have objects that you need to manipulate in different ways. ie. there is functionality associated with the data. (*) Bearing in mind that an "object" can itself be a list/tuple/dict etc So, for your example, the dictionary is probably the most useful structure since you can access the length of any string by looking up the string: eg. print(color_len['blue']) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From neilc at norwich.edu Tue Aug 14 09:05:20 2018 From: neilc at norwich.edu (Neil Cerutti) Date: Tue, 14 Aug 2018 13:05:20 +0000 (UTC) Subject: [Tutor] Is there a better way to write my code? References: Message-ID: On 2018-08-14, Alan Gauld via Tutor wrote: > - Use a list for objects(*) where you might need to > change the value of one of the objects A list is standard practice when you need an ordered collection of objects of the same type, e.g., a bunch of numbers, a bunch of chickens, etc.. It is most efficient when the list may grow and shrink on the end, but becomes suspicious if it usually grows and shrinks in the middle or at the beginning. Nevertheless, Python lists are very often used even so, and only require moving to a different container type when the builtin list start to bog down. > - Use a tuple for objects where you don't need > to change the values (it remains the same during > the life of the program). Yes, a tuple makes an excellent fixed list. A tuple is typically used to store a fixed-size collection of objects of different types, when those objects have some logical connection to one another. If you had only these two containers to choose from for your original exercise--a collection of colors and word-lengths--it might make sense to store the color and wordlength as a tuple, and to store those tuples in a list, on the assumption that more colors might be added. Aside: In Python there's usually no point in storing the length of a string anywhere, since strings store their own length. > - Use a set where you want to eliminate duplicates Sets are great when the most common operations are adding new items and testing for membership, or when you can take advantage of set operations, like union or symmetric difference. If your list of chickens is unordered and has no duplicates, using a set instead is often a good refinement. -- Neil Cerutti From kdeepti2013 at gmail.com Tue Aug 14 04:11:07 2018 From: kdeepti2013 at gmail.com (Deepti K) Date: Tue, 14 Aug 2018 18:11:07 +1000 Subject: [Tutor] Query: lists Message-ID: when I pass ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] as words to the below function, it picks up only 'xzz' and not 'xaa' def front_x(words): # +++your code here+++ a = [] b = [] for z in words: if z.startswith('x'): words.remove(z) b.append(z) print 'z is', z print 'original', sorted(words) print 'new', sorted(b) print sorted(b) + sorted(words) Thanks, Deepti From alan.gauld at yahoo.co.uk Tue Aug 14 17:35:14 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 14 Aug 2018 22:35:14 +0100 Subject: [Tutor] Query: lists In-Reply-To: References: Message-ID: On 14/08/18 09:11, Deepti K wrote: > when I pass ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] as words to the below > function, it picks up only 'xzz' and not 'xaa' Correct because.... > def front_x(words): > # +++your code here+++ > a = [] > b = [] > for z in words: > if z.startswith('x'): > words.remove(z) You just changed the thing you are iterating over. By removing an elem,ent the list got shorter so the internal counter inside the for loop now points at the next item - ie it skipped one. As a general rule never modify the thing you are iterating over with a for loop - use a copy or change to a while loop instead. > b.append(z) > print 'z is', z > print 'original', sorted(words) But it's not the original because you've removed some items. > print 'new', sorted(b) > print sorted(b) + sorted(words) But this should be the same as the original (albeit almost sorted). PS. Since you only modify 'b' and 'words' you don't really need 'a' -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cs at cskk.id.au Tue Aug 14 17:38:01 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Wed, 15 Aug 2018 07:38:01 +1000 Subject: [Tutor] Query: lists In-Reply-To: References: Message-ID: <20180814213801.GA9778@cskk.homeip.net> On 14Aug2018 18:11, Deepti K wrote: > when I pass ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] as words to the below >function, it picks up only 'xzz' and not 'xaa' > >def front_x(words): > # +++your code here+++ > a = [] > b = [] > for z in words: > if z.startswith('x'): > words.remove(z) > b.append(z) > print 'z is', z > print 'original', sorted(words) > print 'new', sorted(b) > print sorted(b) + sorted(words) That is because you are making a common mistake which applies to almost any data structure, but is particularly easy with lists and loops: you are modifying the list _while_ iterating over it. After you go: words.remove(z) all the elements _after_ z (i.e. those after 'xzz' i.e. ['xaa']) are moved down the list. In your particular case, that means that 'xaa' is now at index 3, and the next iteration of the loop would have picked up position 4. Therefore the loop doesn't get to see the value 'xaa'. A "for" loop and almost anything that "iterates" over a data structure does not work by taking a copy of that structure ahead of time, and looping over the values. This is normal, because a data structure may be of any size - you do not want to "make a copy of all the values" by default - that can be arbitrarily expensive. Instead, a for loop obtains an "iterator" of what you ask it to loop over. The iterator for a list effectively has a reference to the list (in order to obtain the values) and a notion of where in the list it is up to (i.e. a list index, a counter starting at 0 for the first element and incrementing until it exceeds the length of the list). So when you run "for z in words", the iterator is up to index 3 when you reach "xzz". So z[3] == "xzz". After you remove "xzz", z[3] == "xaa" and in this case there is no longer a z[4] at all because the list is shortened. So the next loop iteration never inspects that value. Even if the list had more value, the loop would still skip the "xaa" value. You should perhaps ask yourself: why am I removing values from "words"? If you're just trying to obtain the values starting with "x" you do not need to modify words because you're already collecting the values you want in "b". If you're trying to partition words into values starting with "x" and values not starting with "x", you're better off making a separate collection for the "not starting with x" values. And that has me wondering what the list "b" in your code was for originally. As a matter of principle, functions that "compute a value" (in your case, a list of the values starting with "x") should try not to modify what they are given as parameters. When you pass values to Python functions, you are passing a reference, not a new copy. If a function modifies that reference's _content_, as you do when you go "words.move(z)", you're modifying the original. Try running this code: my_words = ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] print 'words before =", my_words front_x(my_words) print 'words after =", my_words You will find that "my_words" has been modified. This is called a "side effect", where calling a function affects something outside it. It is usually undesirable. Cheers, Cameron Simpson From __peter__ at web.de Tue Aug 14 18:16:15 2018 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Aug 2018 00:16:15 +0200 Subject: [Tutor] Query: lists References: Message-ID: Alan Gauld via Tutor wrote: > On 14/08/18 09:11, Deepti K wrote: >> when I pass ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] as words to the below >> function, it picks up only 'xzz' and not 'xaa' > > Correct because.... > >> def front_x(words): >> # +++your code here+++ >> a = [] >> b = [] >> for z in words: >> if z.startswith('x'): >> words.remove(z) > > You just changed the thing you are iterating over. > By removing an elem,ent the list got shorter so the > internal counter inside the for loop now points at > the next item - ie it skipped one. > > As a general rule never modify the thing you are > iterating over with a for loop - use a copy or > change to a while loop instead. > > >> b.append(z) >> print 'z is', z >> print 'original', sorted(words) > > But it's not the original because you've removed > some items. > >> print 'new', sorted(b) >> print sorted(b) + sorted(words) > > But this should be the same as the original > (albeit almost sorted). > > PS. Since you only modify 'b' and 'words' you > don't really need 'a' For a simple solution you do need a and b: leave words unchanged, append words starting with "x" to a and words not starting with "x" to b. Someone familiar with Python might do it with a sort key instead: >>> sorted(['bbb', 'ccc', 'axx', 'xzz', 'xaa'], ... key=lambda s: not s.startswith("x")) ['xzz', 'xaa', 'bbb', 'ccc', 'axx'] If you want ['xaa', 'xzz', 'axx', 'bbb', 'ccc'] as the result you can achieve that by sorting twice (Python's sorting is "stable") or by tweaking the key function. From kdeepti2013 at gmail.com Tue Aug 14 18:36:35 2018 From: kdeepti2013 at gmail.com (Deepti K) Date: Wed, 15 Aug 2018 08:36:35 +1000 Subject: [Tutor] Query: lists In-Reply-To: References: Message-ID: <797DD636-F665-46A1-870E-88C687BB16F3@gmail.com> Thanks all. This is very helpful. I am new to Python :) Sent from my iPhone > On 15 Aug 2018, at 8:16 am, Peter Otten <__peter__ at web.de> wrote: > > Alan Gauld via Tutor wrote: > >>> On 14/08/18 09:11, Deepti K wrote: >>> when I pass ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] as words to the below >>> function, it picks up only 'xzz' and not 'xaa' >> >> Correct because.... >> >>> def front_x(words): >>> # +++your code here+++ >>> a = [] >>> b = [] >>> for z in words: >>> if z.startswith('x'): >>> words.remove(z) >> >> You just changed the thing you are iterating over. >> By removing an elem,ent the list got shorter so the >> internal counter inside the for loop now points at >> the next item - ie it skipped one. >> >> As a general rule never modify the thing you are >> iterating over with a for loop - use a copy or >> change to a while loop instead. >> >> >>> b.append(z) >>> print 'z is', z >>> print 'original', sorted(words) >> >> But it's not the original because you've removed >> some items. >> >>> print 'new', sorted(b) >>> print sorted(b) + sorted(words) >> >> But this should be the same as the original >> (albeit almost sorted). >> >> PS. Since you only modify 'b' and 'words' you >> don't really need 'a' > > For a simple solution you do need a and b: leave words unchanged, append > words starting with "x" to a and words not starting with "x" to b. > > Someone familiar with Python might do it with a sort key instead: > >>>> sorted(['bbb', 'ccc', 'axx', 'xzz', 'xaa'], > ... key=lambda s: not s.startswith("x")) > ['xzz', 'xaa', 'bbb', 'ccc', 'axx'] > > If you want ['xaa', 'xzz', 'axx', 'bbb', 'ccc'] as the result > you can achieve that by sorting twice (Python's sorting is "stable") or by > tweaking the key function. > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From nmadhok at g.clemson.edu Tue Aug 14 18:05:12 2018 From: nmadhok at g.clemson.edu (Nitin Madhok) Date: Tue, 14 Aug 2018 18:05:12 -0400 Subject: [Tutor] Query: lists In-Reply-To: References: Message-ID: <8C80B17A-E43A-4DA4-BE9D-7E92A21ABF8E@g.clemson.edu> Deepti, What you?re seeing happens because you are making changes (words.remove(z)) to the list while you are iterating over it (for z in words). If your goal is to print the original words, removed words and original words without removed words, you could do something like this using sets: words = ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] def front_x(words): # +++your code here+++ removed_words = [] for word in words: if word.startswith('x'): removed_words.append(word) print 'word is', word print 'original', sorted(words) print 'new', sorted(removed_words) print sorted(list(set(removed_words + words))) If you also wanted to get the original words after removing the removed_words, you could print them like this: print 'original - new', list(set(words) - set(removed_words)) Or you could even use list comprehension like this: print 'original - new', [word for word in words if word not in removed_words] -- Thanks, Nitin Madhok Clemson University CONFIDENTIALITY NOTICE This e-mail, and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain privileged and/or confidential information. If you are not the intended recipient of this e-mail, any dissemination, distribution or copying of this e-mail, and any attachments thereto, is strictly prohibited. If you have received this e-mail in error, please immediately notify the sender by e-mail or telephone and permanently delete all copies of this e-mail and any attachments. > On Aug 14, 2018, at 4:11 AM, Deepti K wrote: > > when I pass ['bbb', 'ccc', 'axx', 'xzz', 'xaa'] as words to the below > function, it picks up only 'xzz' and not 'xaa' > > def front_x(words): > # +++your code here+++ > a = [] > b = [] > for z in words: > if z.startswith('x'): > words.remove(z) > b.append(z) > print 'z is', z > print 'original', sorted(words) > print 'new', sorted(b) > print sorted(b) + sorted(words) > > Thanks, > Deepti > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From alan.gauld at yahoo.co.uk Tue Aug 14 19:16:57 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 15 Aug 2018 00:16:57 +0100 Subject: [Tutor] Query: lists In-Reply-To: References: Message-ID: On 14/08/18 23:16, Peter Otten wrote: > For a simple solution you do need a and b: leave words unchanged, append > words starting with "x" to a and words not starting with "x" to b. > > Someone familiar with Python might do it with a sort key instead: Or, for one definition of simple, a list comprehension? filtered_list = [word for word in words if not word.startswith('x')] Of course it doesn't retain the deleted words if that is important. Or if you only want the deleted words simply remove the 'not'. If you need all three results (original, filtered and removed) then you need the original 'a' and 'b' lists as well as the original 'words'. It all depends on what exactly you need as an end result. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Tue Aug 14 19:23:36 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 15 Aug 2018 00:23:36 +0100 Subject: [Tutor] Query: lists In-Reply-To: <20180814213801.GA9778@cskk.homeip.net> References: <20180814213801.GA9778@cskk.homeip.net> Message-ID: On 14/08/18 22:38, Cameron Simpson wrote: > If you're trying to partition words into values starting with "x" and values > not starting with "x", you're better off making a separate collection for the > "not starting with x" values. And that has me wondering what the list "b" in > your code was for originally. And further to Cameron's point this demonstrates why choosing meaningful variable names (rather than single letters) is so important. If a,b and z had been names expressing their purpose we would be better able to guess at your intentions and ultimate goal. But with single letters we have no real clue. > As a matter of principle, functions that "compute a value" (in your case, a > list of the values starting with "x") should try not to modify what they are > given as parameters. When you pass values to Python functions, you are passing > a reference, not a new copy. If a function modifies that reference's _content_, > as you do when you go "words.move(z)", you're modifying the original. It's also good if functions that compute a value *return* that value rather than (or as well as) print it. The act of returning something also helps to clarify the functions objective. With multiple print statements we are not quite sure which line of output is the most important. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From matthew.polack at htlc.vic.edu.au Tue Aug 14 20:56:55 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Wed, 15 Aug 2018 10:56:55 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! Message-ID: Hi, A small group of students and I are making steady progress learning Python. Thanks for the people here who have helped us! I have an problem with my simple 'Times Tables Program'. The 'Make Problem' function works fine...it can generate a random problem and place it in a variable called "answer"...which I've made global because it needs to be used in the 'Check answer' function. The trouble is the program is unable to tell you that you are right....even when you type in the correct answer. Here is the full code: from tkinter import * import random answer = "global" def makeproblem(): # deletes anything in text box from location 00 to the end txt.delete(0.0, 'end') sentence = "Your first problem is " number1 = random.randint(2,12) number2 = random.randint(2,12) answer = number1 * number2 txt.insert(0.0, sentence) txt.insert(2.2, number1) txt.insert(3.3, " x ") txt.insert(4.4, number2) def checkanswer(): # deletes anything in text box from location 00 to the end txt.delete(0.0, 'end') # checks for what is written in answerbox response = int(answerbox.get()) if response == answer: result = "Great Job!" score = int(score + 1) else : result = "Sorry...you were wrong" txt.insert(0.0, result) txt.insert(1,1, "Score is") txt.insert(2,2, score) root = Tk() root.geometry("640x640+0+0") root.title("Times Tables") timeslabel = Label(root, text="Times Tables Practice", fg="white", bg="blue", font=("arial", 36, "bold")) timeslabel.grid(columnspan=12, sticky='ew') instruction = Label(root, text="Please click on the button to generate a problem", fg="blue", bg="white", font=("arial", 16, "bold")) instruction.grid(row=2, columnspan=20) blankline = Label(root, text = "", bg = "white") blankline.grid(row=12, sticky='ew') # Makes an entry box with the variable of 'answerbox' answerbox = Entry(root, bg="aqua", font=("arial", 24, "bold")) answerbox.grid(row=15, columnspan=2, sticky=EW) # Makes a button that generate the Times Tables problem btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", command= makeproblem) btn.grid(row=11, columnspan=2, sticky=EW) # Makes a button that checks the answer btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", command= checkanswer) btn.grid(row=13, columnspan=2, sticky=EW) #HOW CAN I CENTRE THE TEXT??? txt = Text(root, width=35, height=10, wrap=WORD, font=("arial", 24, "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) root.mainloop() *Question 1:* *Why cant the program check if 'answer' variable is correct?* lib\tkinter\__init__.py", line 3269, in insert self.tk.call((self._w, 'insert', index, chars) + args) _tkinter.TclError: bad text index "1" *Question 2:* Is there a way to centre text within the text frame? I can change the font and size...but don't know how to centre it? txt = Text(root, width=35, height=10, wrap=WORD, font=("arial", 24, "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) *Question 3:* My 'Score' check idea..may not actually work...haven't been able to get that far yet though! Thanks so much for any clues. - Matthew Polack Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From rafael.knuth at gmail.com Wed Aug 15 03:32:28 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Wed, 15 Aug 2018 09:32:28 +0200 Subject: [Tutor] understanding Python naming conventions & semantics Message-ID: I am trying to wrap my head around naming conventions & semantics in Python. Here are two code snippets, and below those two snippets are my questions: # code snippet 1 file_path = "C:\\Users\\...etl.csv" with open(file_path) as file_object: contents = file_object.read() contents_split = contents.split("\n") print(contents_split[:3]) ['Year,Week,Winner,Loser', '1966,1,Miami Dolphins,Oakland Raiders', '1966,1,Houston Oilers,Denver Broncos'] # code snippet 2 file_path = "C:\\Users\\...etl.csv" with open(file_path) as file_object: contents = list(file_object) print(contents[:3]) ['Year,Week,Winner,Loser\n', '1966,1,Miami Dolphins,Oakland Raiders\n', '1966,1,Houston Oilers,Denver Broncos\n'] Here are my questions: - List is a function, and read is a method, is that correct? - Semantic wise it would be always like function(something) and a method would be something.method() .. is that correct? - Assuming the above is correct, it seems that there is a tiny line between methods and functions? Why is something a method or a function? - For example, why is print a function and not a method? something.print() instead of print(something) Just trying to understand logic of Python and conventions, which will then make learning and memorizing things easier. Thanks. From alan.gauld at yahoo.co.uk Wed Aug 15 04:25:06 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 15 Aug 2018 09:25:06 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 15/08/18 01:56, Matthew Polack wrote: > from tkinter import * > > import random > > answer = "global" You have the right concept but the wrong implementation. To declare a variable as global you declare it as normal in the outer scope then inside each function that uses it add a global line which, in this case, looks like global answer So your code should look like: answer = 0 # placeholder value def makeProblem(): global answer # access global answer .... def checkAnswer(): global answer .... BTW, Please post messages in plain text not HTML/RTF because otherwise we lose all the formatting which is critical in understanding the code. > def makeproblem(): > # deletes anything in text box from location 00 to the end > txt.delete(0.0, 'end') > sentence = "Your first problem is " > > number1 = random.randint(2,12) > number2 = random.randint(2,12) > answer = number1 * number2 without the global line at the top this create a local variable inside the function which is then lost when the function exits > txt.insert(0.0, sentence) > txt.insert(2.2, number1) > txt.insert(3.3, " x ") > txt.insert(4.4, number2) > > def checkanswer(): > # deletes anything in text box from location 00 to the end > txt.delete(0.0, 'end') > > # checks for what is written in answerbox > response = int(answerbox.get()) > if response == answer: This compares response to the global answer which has the value "global", so it is never equal. > result = "Great Job!" > score = int(score + 1) > else : > result = "Sorry...you were wrong" > txt.insert(0.0, result) > txt.insert(1,1, "Score is") > txt.insert(2,2, score) > > root = Tk() > root.geometry("640x640+0+0") > root.title("Times Tables") > > > timeslabel = Label(root, text="Times Tables Practice", fg="white", bg="blue", > font=("arial", 36, "bold")) > timeslabel.grid(columnspan=12, sticky='ew') > instruction = Label(root, text="Please click on the button to generate a > problem", fg="blue", bg="white", font=("arial", 16, "bold")) > instruction.grid(row=2, columnspan=20) > > blankline = Label(root, text = "", bg = "white") > blankline.grid(row=12, sticky='ew') > > # Makes an entry box with the variable of 'answerbox' > answerbox = Entry(root, bg="aqua", font=("arial", 24, "bold")) > answerbox.grid(row=15, columnspan=2, sticky=EW) > > # Makes a button that generate the Times Tables problem > btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", command= > makeproblem) > btn.grid(row=11, columnspan=2, sticky=EW) > > # Makes a button that checks the answer > btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", command= > checkanswer) > btn.grid(row=13, columnspan=2, sticky=EW) > > #HOW CAN I CENTRE THE TEXT??? If you mean the widget look at the fill and padding attributes of the layout manager. If you mean the text inside the widget look at the string formatting methods. Especiially center(), ljust() and rjust(). Its messy but with patience and suitable font selection it works. I don't know any other way in Tkinter, so usually stick with left aligned! > txt = Text(root, width=35, height=10, wrap=WORD, font=("arial", 24, "bold")) > txt.grid(row=12, columnspan=2, sticky=EW ) > > root.mainloop() > > > *Question 1:* > *Why cant the program check if 'answer' variable is correct?* See use of global above > *Question 2:* > Is there a way to centre text within the text frame? I can change the font > and size...but don't know how to centre it? Only with difficulty. See above. > *Question 3:* > My 'Score' check idea..may not actually work...haven't been able to get > that far yet though! It should work but you need to make score a global variable too or else the score will be thrown away when the function ends. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From ben+python at benfinney.id.au Wed Aug 15 04:30:13 2018 From: ben+python at benfinney.id.au (Ben Finney) Date: Wed, 15 Aug 2018 18:30:13 +1000 Subject: [Tutor] understanding Python naming conventions & semantics References: Message-ID: <867eksniay.fsf@benfinney.id.au> Rafael Knuth writes: > - List is a function, and read is a method, is that correct? * No, ?list? is a type. Types are callable; they return an instance of the type. * Yes, a file object has a ?read? method. * Every method is a function. Not every function is a method. > - Semantic wise it would be always like function(something) and a > method would be something.method() .. is that correct? You have shown the syntax for referring to an object and calling it. The reference syntax will not help you know whether an object is a method. The calling syntax will not help you know whether an object is a method. > - Assuming the above is correct, it seems that there is a tiny line > between methods and functions? Why is something a method or a > function? * Every method is a function. * A function is a method if it is defined in a class. > - For example, why is print a function and not a method? Because the ?print? function is not defined in a class. > Just trying to understand logic of Python and conventions, which will > then make learning and memorizing things easier. You may want to refer to the documentation frequently. The Glossary can help with questions like this. -- \ ?Not using Microsoft products is like being a non-smoker 40 or | `\ 50 years ago: You can choose not to smoke, yourself, but it's | _o__) hard to avoid second-hand smoke.? ?Michael Tiemann | Ben Finney From alan.gauld at yahoo.co.uk Wed Aug 15 04:41:31 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 15 Aug 2018 09:41:31 +0100 Subject: [Tutor] understanding Python naming conventions & semantics In-Reply-To: References: Message-ID: On 15/08/18 08:32, Rafael Knuth wrote: > I am trying to wrap my head around naming conventions & semantics in Python. A good question with a none to simple answer. In truth some of it goes back to essentially arbitrary decisions made by Guido vanRossum when he originally designed Python! The other key concept to remember is that methods are functions attached (bound) to an object(class) and that every value is Python is an object. And that includes functions! > Here are my questions: > > - List is a function, and read is a method, is that correct? Yes, although list() can also be though of as an object constructor - it creates instances of list objects > - Semantic wise it would be always like function(something) and a > method would be something.method() .. is that correct? Yes. Methods are accessed via their object. It is also possible (but usually a bad idea) to call methods via their class like functions: aClass.method(theObject, something,...) > - Assuming the above is correct, it seems that there is a tiny line > between methods and functions? Why is something a method or a > function? As mentioned above methods are functions. But they are functions attached to objects. Thats what makes them methods. They are defined in the class definition from which the object is instantiated. They have a tiny bit of magic associated with them in that the first parameter of a method is a placeholder for the object it works on - usually called self. When you call a method Python looks up the original class and calls the function defined there and substitutes the current object for self, thus: class MyClass: def method(self): pass myObject = MyClass() # create an object myObject.method() is now converted by Python to: myClass.method(myObject) > - For example, why is print a function and not a method? > something.print() instead of print(something) Because print can print anything, its not restricted to a single class of object. (Although it could have been defined at the "object" level and thus apply to all objects. But thats the arbitrary choice Guido made.) There are other similar functions like len() There are also rather confusingly some commands. They look like functions but don't require parens. The most common is probably del x = 42 del x # not del(x), although that works too. print was a command in Python 2 but got converted to a function in Python 3. For some reason del and a few others did not... > Just trying to understand logic of Python and conventions, which will > then make learning and memorizing things easier. A good thing to do but in some cases you have to settle for "that's just the way Guido made it" :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Wed Aug 15 04:55:15 2018 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Aug 2018 10:55:15 +0200 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! References: Message-ID: Matthew Polack wrote: > *Question 1:* > > *Why cant the program check if 'answer' variable is correct?* Change the line result = "Sorry...you were wrong. in your script to result = "Sorry...you were wrong. Expected {!r}, but got {!r}".format(answer, response) and find out yourself. Hint: answer in the makeproblem() function is not a global variable. > lib\tkinter\__init__.py", line 3269, in insert > self.tk.call((self._w, 'insert', index, chars) + args) > _tkinter.TclError: bad text index "1" The first argument of the Text.insert() is a string in a special format. Read http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/text-index.html http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/text-methods.html for the details. You have a mix of one float (which may work by accident) or two integers (which raises an exception). > *Question 2:* > Is there a way to centre text within the text frame? I can change the font > and size...but don't know how to centre it? I don't know, and I'm too lazy to google ;) > txt = Text(root, width=35, height=10, wrap=WORD, font=("arial", 24, > "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) > > > *Question 3:* > > My 'Score' check idea..may not actually work...haven't been able to get > that far yet though! The score variable is not declared global and not initialised. You cannot increment something that doesn't exist. > Thanks so much for any clues. > > - Matthew Polack > > > > > > > > Matthew Polack | Teacher > > > [image: Emailbanner3.png] > > Trinity Drive | PO Box 822 > > Horsham Victoria 3402 > > p. 03 5382 2529 m. 0402456854 > > e. matthew.polack at htlc.vic.edu.au > > w. www.htlc.vic.edu.au > From __peter__ at web.de Wed Aug 15 05:18:09 2018 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Aug 2018 11:18:09 +0200 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! References: Message-ID: Matthew Polack wrote: > *Question 2:* > Is there a way to centre text within the text frame? I can change the font > and size...but don't know how to centre it? Ok, I wanted to know it myself, and found https://stackoverflow.com/questions/42560585/how-do-i-center-text-in-the-tkinter-text-widget From alan.gauld at yahoo.co.uk Wed Aug 15 06:10:16 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 15 Aug 2018 11:10:16 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 15/08/18 10:18, Peter Otten wrote: > Matthew Polack wrote: > >> *Question 2:* >> Is there a way to centre text within the text frame? I can change the font >> and size...but don't know how to centre it? > > Ok, I wanted to know it myself, and found > > https://stackoverflow.com/questions/42560585/how-do-i-center-text-in-the-tkinter-text-widget Well done Peter. I've looked for ways to do this (and other format tricks) several times and failed. I never thought of looking at tags though... Using the string methods as I suggested relies on using monospace fonts, and splitting the text manually into lines of appropriate length - a major pain. This works with proportional fonts and long text too. So much better. Thanks again for your superior google skills :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From matthew.polack at htlc.vic.edu.au Wed Aug 15 07:29:51 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Wed, 15 Aug 2018 21:29:51 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: Thanks Alan and Peter, Really appreciate your replies. Will try this out tomorrow and see if I can get it to work. I keep googling things myself...but with my 'beginner' status sometimes struggle to understand the solutions out there....but in tiny steps am making progress! Certainly know a lot more than when I started 4 weeks ago! Thank you so much for your support and time replying....it is very encouraging. - Matthew Polack Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Wed, Aug 15, 2018 at 8:10 PM, Alan Gauld via Tutor wrote: > On 15/08/18 10:18, Peter Otten wrote: > > Matthew Polack wrote: > > > >> *Question 2:* > >> Is there a way to centre text within the text frame? I can change the > font > >> and size...but don't know how to centre it? > > > > Ok, I wanted to know it myself, and found > > > > https://stackoverflow.com/questions/42560585/how-do-i- > center-text-in-the-tkinter-text-widget > > Well done Peter. I've looked for ways to do this > (and other format tricks) several times and > failed. I never thought of looking at tags though... > > Using the string methods as I suggested relies on > using monospace fonts, and splitting the text > manually into lines of appropriate length - a major > pain. > > This works with proportional fonts and long text too. > So much better. > > Thanks again for your superior google skills :-) > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From rafael.knuth at gmail.com Wed Aug 15 05:11:33 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Wed, 15 Aug 2018 11:11:33 +0200 Subject: [Tutor] understanding Python naming conventions & semantics In-Reply-To: References: Message-ID: > A good thing to do but in some cases you have > to settle for "that's just the way Guido made it" :-) Thanks for the elaborate answer. That helps me a lot, as I see some similarities to natural languages: There is a clearly defined structure, but in some cases purely arbitrary decisions have been made (aka exceptions). After all, we're all humans, and we're not living in a perfect world. I naively believed, that in a programming language everything is perfectly well structured (Python is my first programming language). Knowing that this is not the case, makes my learning efforts much easier, as I can always check whether something is a rule or exception in the first place. If it's an exception, I have to memorize it, if it's a rule, I need to understand where it fits into the overall concept of Python. Another important distinction (for me) is that context matters. Such as, for example, that methods are functions associated with objects. (huh, reminds me a bit of Mandarin Chinese where context is (almost) everything) In the end, practice matters ;-) Thank you again! From hamidnehoray at yahoo.com Wed Aug 15 13:45:59 2018 From: hamidnehoray at yahoo.com (Hamid Nehoray) Date: Wed, 15 Aug 2018 17:45:59 +0000 (UTC) Subject: [Tutor] Need PYTHON, MySQL, WEB2PY OR DJANGO Tutor References: <8741372.8517876.1534355159505.ref@mail.yahoo.com> Message-ID: <8741372.8517876.1534355159505@mail.yahoo.com> Greetings,I'm an old programmer who has some old ERP systems deployed in few companies.? I need somebody to teach me the new ways using Python, MySql and Web2Py or Django.? I'm located in Los Angeles.Regards,Hamid Nehoray. From matthew.polack at htlc.vic.edu.au Thu Aug 16 03:18:33 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Thu, 16 Aug 2018 17:18:33 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: Hi All, Thanks to your help I've nearly got my demo 'Times Tables' program fully working. The last remaining issue is the program does not calculate the percentage right when you make mistakes...it just keeps giving a result of 100%. I've looked and head scratched...and am not sure. Can anyone figure out what is wrong with this code? Thanks! - Matt from tkinter import * import random answer = 0 score = 0 wrong = 0 mistakes = 0 percentScore = 0 total = 0 def percentCheck(): global percentScore global score global mistakes global total percentScore = float(score/total) * 100 viewPercent() def makeproblem(): # deletes anything in text box from location 00 to the end global answer # access global answer txt.delete(0.0, 'end') sentence = "Here is your problem " number1 = random.randint(2,12) number2 = random.randint(2,12) answer = number1 * number2 txt.insert(0.0, sentence) txt.insert(2.2, number1) txt.insert(3.3, " x ") txt.insert(4.4, number2) def checkanswer(): # deletes anything in text box from location 00 to the end txt.delete(0.0, 'end') global answer global score global wrong global mistakes global percentScore global total # checks for what is written in answerbox response = int(answerbox.get()) wordScore = "Your score is now " if response == answer: score = int(score + 1) total = int(total + 1) result = "Great Job! " root.update() viewSC() percentCheck() viewPercent() viewTotal() else : score= int(score + 1) total = int(total + 1) result = "Sorry...you were wrong" mistakes = int(mistakes + 1) viewWrong() viewTotal() percentCheck() viewPercent() txt.insert(0.0, result) txt.insert(3.0, wordScore) txt.insert(8.1, score) # txt.insert(1,1, "Score is") #txt.insert(3,3, score) root = Tk() root.geometry("640x700+0+0") root.title("Times Tables") timeslabel = Label(root, text="Times Tables Practice", fg="white", bg="blue", font=("arial", 36, "bold")) timeslabel.grid(columnspan=12, sticky='ew') instruction = Label(root, text="Please click on the button to generate a problem", fg="blue", bg="white", font=("arial", 16, "bold")) instruction.grid(row=2, columnspan=20) blankline = Label(root, text = "", bg = "white") blankline.grid(row=12, sticky='ew') # Makes an entry box with the variable of 'answerbox' answerbox = Entry(root, bg="aqua", font=("arial", 24, "bold")) answerbox.grid(row=15, columnspan=2, sticky=EW) # Makes a button that generate the Times Tables problem btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", command=makeproblem) btn.grid(row=11, columnspan=2, sticky=EW) # Makes a button that checks the answer btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", command=checkanswer) btn.grid(row=13, columnspan=2, sticky=EW) #HOW CAN I CENTRE THE TEXT??? txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 24, "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) blankline3 = Label(root, text = "", bg = "white") blankline3.grid(row=17, sticky='ew') scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial", 20, "bold")) scorelab.grid(row=18, column=0, sticky=E) totalLab = Label(root, text="Out of", bg="purple", fg="white", font=("arial", 20, "bold")) totalLab.grid(row=19, column=0, sticky=E) wronglab = Label(root, text="Mistakes", bg="red", fg="white", font=("arial", 20, "bold")) wronglab.grid(row=20, column=0, sticky=E) percentlab = Label(root, text="Percentage", bg="aqua", fg="white", font=("arial", 20, "bold")) percentlab.grid(row=21, column=0, sticky=E) def viewSC(): global score #scoreViewLab=Label(root, scoreView, textvariable=scoreView) scoreViewLab = Label(root, text=score, fg="black", bg="grey", font=("arial", 20, "bold")) scoreViewLab.grid(row=18, column=1, sticky=W) def viewTotal(): global total #scoreViewLab=Label(root, scoreView, textvariable=scoreView) totalViewLab = Label(root, text=total, fg="black", bg="grey", font=("arial", 20, "bold")) totalViewLab.grid(row=19, column=1, sticky=W) def viewWrong(): global wrong global mistakes #scoreViewLab=Label(root, scoreView, textvariable=scoreView) wrongViewLab = Label(root, text=mistakes, fg="black", bg="grey", font=("arial", 20, "bold")) wrongViewLab.grid(row=20, column=1, sticky=W) def viewPercent(): global percentScore global total global score #scoreViewLab=Label(root, scoreView, textvariable=scoreView) percentViewLab = Label(root, text=percentScore, fg="black", bg="grey", font=("arial", 20, "bold")) percentViewLab.grid(row=21, column=1, sticky=W) viewSC() viewWrong() viewPercent() viewTotal() root.mainloop() Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Wed, Aug 15, 2018 at 9:29 PM, Matthew Polack < matthew.polack at htlc.vic.edu.au> wrote: > Thanks Alan and Peter, > > Really appreciate your replies. Will try this out tomorrow and see if I > can get it to work. > > I keep googling things myself...but with my 'beginner' status sometimes > struggle to understand the solutions out there....but in tiny steps am > making progress! > > Certainly know a lot more than when I started 4 weeks ago! > > Thank you so much for your support and time replying....it is very > encouraging. > > - Matthew Polack > > Matthew Polack | Teacher > > > [image: Emailbanner3.png] > > Trinity Drive | PO Box 822 > > Horsham Victoria 3402 > > p. 03 5382 2529 m. 0402456854 > > e. matthew.polack at htlc.vic.edu.au > > w. www.htlc.vic.edu.au > > On Wed, Aug 15, 2018 at 8:10 PM, Alan Gauld via Tutor > wrote: > >> On 15/08/18 10:18, Peter Otten wrote: >> > Matthew Polack wrote: >> > >> >> *Question 2:* >> >> Is there a way to centre text within the text frame? I can change the >> font >> >> and size...but don't know how to centre it? >> > >> > Ok, I wanted to know it myself, and found >> > >> > https://stackoverflow.com/questions/42560585/how-do-i-center >> -text-in-the-tkinter-text-widget >> >> Well done Peter. I've looked for ways to do this >> (and other format tricks) several times and >> failed. I never thought of looking at tags though... >> >> Using the string methods as I suggested relies on >> using monospace fonts, and splitting the text >> manually into lines of appropriate length - a major >> pain. >> >> This works with proportional fonts and long text too. >> So much better. >> >> Thanks again for your superior google skills :-) >> >> -- >> Alan G >> Author of the Learn to Program web site >> http://www.alan-g.me.uk/ >> http://www.amazon.com/author/alan_gauld >> Follow my photo-blog on Flickr at: >> http://www.flickr.com/photos/alangauldphotos >> >> >> _______________________________________________ >> Tutor maillist - Tutor at python.org >> To unsubscribe or change subscription options: >> https://mail.python.org/mailman/listinfo/tutor >> > > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From alan.gauld at yahoo.co.uk Thu Aug 16 04:28:38 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 16 Aug 2018 09:28:38 +0100 Subject: [Tutor] Need PYTHON, MySQL, WEB2PY OR DJANGO Tutor In-Reply-To: <8741372.8517876.1534355159505@mail.yahoo.com> References: <8741372.8517876.1534355159505.ref@mail.yahoo.com> <8741372.8517876.1534355159505@mail.yahoo.com> Message-ID: On 15/08/18 18:45, Hamid Nehoray via Tutor wrote: > Greetings, Greetings, welcome to the tutor list. > I'm an old programmer who has some old ERP systems... > I need somebody to teach me the new ways using Python, For anyone who can already program I always recommend starting with the official Python tutorial: http://docs.python.org/tut/ > MySql There is a MySQL tutorial on their web site, but I've never used it. However, if you are familiar with any major SQL database(Oracle, DB2, etc) then you should pick it up easily. > and Web2Py or Django.? Django has some excellent tutorials although I usually recommend watching a few YouTube videos to get a feel for things first. Then dive into the detail with a written tut. but you will need to have completed the Python tutorial(above0 first. A know nothing about Web2py... > I'm located in Los Angeles.Regards,Hamid Nehoray. The tutor list works by answering your questions as you post them to the list. Please always use plain text to retain formatting. Always post the full text of error messages not just a summary. And tell us the OS and Python versions. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Thu Aug 16 05:09:51 2018 From: __peter__ at web.de (Peter Otten) Date: Thu, 16 Aug 2018 11:09:51 +0200 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! References: Message-ID: Matthew Polack wrote: > Hi All, > > Thanks to your help I've nearly got my demo 'Times Tables' program fully > working. > > The last remaining issue is the program does not calculate the percentage > right when you make mistakes...it just keeps giving a result of 100%. > > I've looked and head scratched...and am not sure. > > Can anyone figure out what is wrong with this code? You increment the score no matter whether the answer is correct or not. > if response == answer: > score = int(score + 1) > else : > score= int(score + 1) Random remarks - Your code suffers from "over-globalisation". You only need to declare a variable global when you want to change it from within a function. Example: x = 0 def show_x(): # no global necessary print("x =", x) def inc_x(): global x x += 1 - You create a new Label in every call of viewXXX(). For long-running applications that will consume a lot of memory. You should instead create the label once and then update it percentViewLab = Label(...) percentViewLab.grid(...) def viewPercent(): percentViewLab["text"] = percentScore - You convert integers to integers. > score = int(score + 1) should better be written score = score + 1 or score += 1 - I rarely say that, but you have too many functions -- or rather you have written them in such a way that you need to call them in a special order. Personally I would omit the percentCheck function and the percentScore variable and rewrite viewPercent as def viewPercent(): percentViewLab["text"] = score/total*100 or if you want to keep the function def get_percent_score(): return score/total*100 def viewPercent(): percentViewLab["text"] = get_percent_score() With both approaches viewPercent() can never show an out-of-date value. From alan.gauld at yahoo.co.uk Thu Aug 16 05:11:23 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 16 Aug 2018 10:11:23 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 16/08/18 08:18, Matthew Polack wrote: > The last remaining issue is the program does not calculate the percentage > right when you make mistakes...it just keeps giving a result of 100%. > def percentCheck(): > global percentScore > global score > global mistakes > global total While you do need some globals in your program you only need to declare the ones you are changing. In this case you only need to declare percentScore as global. > percentScore = float(score/total) * 100 To debug this I would add a print line such as print(score, total) Since if you always get 100 it suggests that score and total are the same. One problem here is that you are converting to float after doing the division. That's usually the wrong thing to do. In fact I notice you do that a lot of conversions on expressions. Its much safer to do the conversions on the individual values then perform the computation after the conversion. In fact in this case (and most of the other similar cases) you should not need the float conversion since you already converted the values when you read them from the GUI. You should aim to convert the data into the correct type as soon as possible then you will not need to use conversions anywhere else. Some more observations below... > viewPercent() > > > def makeproblem(): > # deletes anything in text box from location 00 to the end > global answer # access global answer > > txt.delete(0.0, 'end') > > sentence = "Here is your problem " > > number1 = random.randint(2,12) > number2 = random.randint(2,12) > > answer = number1 * number2 > > txt.insert(0.0, sentence) > txt.insert(2.2, number1) > txt.insert(3.3, " x ") > txt.insert(4.4, number2) > > def checkanswer(): > # deletes anything in text box from location 00 to the end > txt.delete(0.0, 'end') > > global answer > global score > global wrong > global mistakes > global percentScore > global total > > # checks for what is written in answerbox > response = int(answerbox.get()) > wordScore = "Your score is now " > > if response == answer: > score = int(score + 1) > total = int(total + 1) .... > else : > score= int(score + 1) > total = int(total + 1) Notice that regardless of what the answer is you update both score and total. And again you don't need the int() conversions, the variables are already integers. > root = Tk() > root.geometry("640x700+0+0") > root.title("Times Tables") > > > #HOW CAN I CENTRE THE TEXT??? > txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 24, "bold")) > txt.grid(row=12, columnspan=2, sticky=EW ) AS per Peter's link you need to create a tag and configure it with the font and justification you want. Then when you insert the text you add the tag name. eg: center = txt.tag_config("center", justify="center") txt.insert(1.0, "Hello world", "center") > blankline3 = Label(root, text = "", bg = "white") > blankline3.grid(row=17, sticky='ew') I'm not sure what this is for. If you want some space just add some padding to the label below. > scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial", > 20, "bold")) > scorelab.grid(row=18, column=0, sticky=E) Note that you create a Label here, but in ViewSC below you create another label which causes this one to be deleted. This is not necessary, instead just change the text of this label in viewSC. scorelab['text'] = "New text here" > totalLab = Label(root, text="Out of", bg="purple", fg="white", > font=("arial", 20, "bold")) > totalLab.grid(row=19, column=0, sticky=E) Same applies to the other viewXXX functions, just update these labels, don't build and destroy new label widgets each time. That's a lot of wasted work and time for your PC. > def viewSC(): > global score You don't change score so no need for global here. You only need global when changing the data. > scoreViewLab = Label(root, text=score, fg="black", bg="grey", > font=("arial", 20, "bold")) > scoreViewLab.grid(row=18, column=1, sticky=W) I just noticed this is in a different grid location, but the principle still applies create it once at the start of the GUI then update it in the view functions. > def viewTotal(): > global total > #scoreViewLab=Label(root, scoreView, textvariable=scoreView) > totalViewLab = Label(root, text=total, fg="black", bg="grey", > font=("arial", 20, "bold")) > totalViewLab.grid(row=19, column=1, sticky=W) > > def viewWrong(): > global wrong > global mistakes > > #scoreViewLab=Label(root, scoreView, textvariable=scoreView) > wrongViewLab = Label(root, text=mistakes, fg="black", bg="grey", > font=("arial", 20, "bold")) > wrongViewLab.grid(row=20, column=1, sticky=W) You declare wrong as global but never use it. Should this function not be called viewMistakes? > def viewPercent(): > global percentScore > global total > global score > #scoreViewLab=Label(root, scoreView, textvariable=scoreView) > percentViewLab = Label(root, text=percentScore, fg="black", bg="grey", > font=("arial", 20, "bold")) > percentViewLab.grid(row=21, column=1, sticky=W) > viewSC() > viewWrong() > viewPercent() > viewTotal() > > root.mainloop( While your code sort of works its doing an awful lot of work that it doesn't need to do. You need to stop and think through why you use each global and type conversions and only keep the ones you really need. Similarly you should only need to create the widgets once when you build the GUI. After that its just a matter of updating the content. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From matthew.polack at htlc.vic.edu.au Thu Aug 16 22:19:15 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Fri, 17 Aug 2018 12:19:15 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: Thanks Alan and Peter, I've gone through and made a bunch of changes based on all your advice. Thank you...everything seems to be fully working and I think I have made the code more efficient using your advice...hope I got everything. (full code below) I've just added an example menu to highlight the concept for teachers or students to refer to. 2 questions: 1.) Centre feature When I use txt.insert I need to use the feature Peter found... center = txt.tag_config("center", justify="center") txt.insert(0.0, result, "center") but in the Enter label section...I could just use it straight away..without defining it with the tag... answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify ="center") answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) Can you explain why? 2.) When inserting the wording re: 'You have made mistake' or 'Great job' etc...I found I had to break it up into separate lines...as I was getting syntax errors. txt.insert(0.0, result, "center") txt.insert(3.0, wordScore, "center") txt.insert(8.1, score, "center") Is there a way to simply combine all these commands with one txt.insert and using commas? 3.) Is there anything else in this code that looks like a bit of a glaring...'Coding Rookie' mistake? Or is simply inefficient? Thanks again for all your help. I've found things are starting to make a lot more sense...and googling things now let me add other features. eg. The rounding function here: def viewPercent(): percentCalc = score/total*100 rounded = round(percentCalc, 2) percentViewLab["text"] = rounded Thank you Peter and Allan..and others here who have helped on the journey. from tkinter import * import random # GLOBAL VARIABLES # Created with a starting value. answer = 0 score = 0 wrong = 0 mistakes = 0 total = 0 def makeproblem(): # access global answer...this is only required IF you need to update the variable within the function. # this happens below when answer is changed to number1 * number2 global answer # erases all text in current text box. txt.delete(0.0, 'end') sentence = "Here is your problem " # example of generating a random number. number1 = random.randint(2,12) number2 = random.randint(2,12) answer = number1 * number2 # creates a justification command called centre. (Not too sure why this is needed here...but not on the answer box elsewhere!) center = txt.tag_config("center", justify="center") txt.insert(0.0, sentence, "center") txt.insert(2.2, number1, "center") txt.insert(3.3, " x ", "center") txt.insert(4.4, number2, "center") def checkanswer(): txt.delete(0.0, 'end') # as each variable changes outside of function...we need to make these global. global score global mistakes global total # checks for what is written in answerbox using the 'get' feature...makes it an integer. response = int(answerbox.get()) wordScore = "Your score is now " if response == answer: score += 1 total += 1 result = "Great Job! " root.update() viewSC() viewPercent() viewTotal() else : total += 1 result = "Sorry...you made a mistake. \n " # the \n above adds a line break. mistakes += 1 viewMistakes() viewTotal() viewPercent() center = txt.tag_config("center", justify="center") txt.insert(0.0, result, "center") txt.insert(3.0, wordScore, "center") txt.insert(8.1, score, "center") # txt.insert(1,1, "Score is") #txt.insert(3,3, score) def about(): txt.delete(0.0, 'end') instructions = "Here is how you play the game. Press generate problem..and then enter your answer. Your score will be displayed below." txt.insert(0.0,instructions) root = Tk() root.geometry("640x700+0+0") root.title("Times Tables Game") # MENU SECTION # These are included as an example menu structure...in many cases they don't do much...but do feature instructions and a quit feature. # create a toplevel menu menubar = Menu(root) # Just an example of printing hello to console for use in a menu item. def hello(): print ("hello!") # display the menu root.config(menu=menubar) # create a pulldown menu, and adds it to the menu bar filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Open", command=makeproblem) filemenu.add_command(label="Save", command=makeproblem) filemenu.add_separator() filemenu.add_command(label="Exit", command=root.quit) menubar.add_cascade(label="File", menu=filemenu) # create more pulldown menus editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label="Cut", command=checkanswer) editmenu.add_command(label="Copy", command=checkanswer) editmenu.add_command(label="Paste", command=checkanswer) menubar.add_cascade(label="Edit", menu=editmenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="About", command=about) menubar.add_command(label="Hello", command=hello) menubar.add_cascade(label="Help", menu=helpmenu) menubar.add_command(label="Quit", command=root.quit) # Plain text labels at top of window. timeslabel = Label(root, text="Times Tables Practice", fg="white", bg="blue", font=("arial", 36, "bold")) timeslabel.grid(columnspan=12, sticky='ew') instruction = Label(root, text="Please click on the button to generate a problem", fg="blue", bg="white", font=("arial", 16, "bold")) instruction.grid(row=2, columnspan=20) # Makes an entry box with the variable of 'answerbox' answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify ="center") answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) # Makes a button that generate the Times Tables problem btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", command=makeproblem) btn.grid(row=11, columnspan=2, sticky=EW) # Makes a button that checks the answer btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", command=checkanswer) btn.grid(row=13, columnspan=2, sticky=EW) #TEXT BOX AREA #This important command creates the text box called 'txt'. This is used for all the text output. txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 20, "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) #Adds a blankline below answer box...but leaves top alignment alone. You could use PAD...but that command does both sides. There may be another way to achieve this. blankline3 = Label(root, text = "", bg = "white") blankline3.grid(row=17, sticky='ew') # SCORING LABELS AND RESULTS SECTION # Places the labels and the results beside each other in column 0 and column 1. # Note: Each 'View' label grabs the starting score from the declarations at the top. eg. score = 0 scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial", 20, "bold")) scorelab.grid(row=18, column=0, sticky=E) scoreViewLab = Label(root, text=score, fg="black", bg="grey", font=("arial", 20, "bold")) scoreViewLab.grid(row=18, column=1, sticky=W) totalLab = Label(root, text="Out of", bg="purple", fg="white", font=("arial", 20, "bold")) totalLab.grid(row=19, column=0, sticky=E) totalViewLab = Label(root, text=total, fg="black", bg="grey", font=("arial", 20, "bold")) totalViewLab.grid(row=19, column=1, sticky=W) mistakeslab = Label(root, text="Mistakes", bg="red", fg="white", font=("arial", 20, "bold")) mistakeslab.grid(row=20, column=0, sticky=E) mistakesViewLab = Label(root, text=mistakes, fg="black", bg="grey", font=("arial", 20, "bold")) mistakesViewLab.grid(row=20, column=1, sticky=W) percentlab = Label(root, text="Percentage", bg="aqua", fg="white", font=("arial", 20, "bold")) percentlab.grid(row=21, column=0, sticky=E) percentViewLab = Label(root, text=0, fg="black", bg="grey", font=("arial", 20, "bold")) percentViewLab.grid(row=21, column=1, sticky=W) #SCORE UPDATE SECTION. # Each of these functions allows the 4 scoring labels to be updated as answers are deemed correct or incorrect with the if/else statement. # The viewPercent function includes the calculation to update the percentView label...shows an example of a calculation within a label. def viewSC(): scoreViewLab["text"] = score def viewTotal(): totalViewLab["text"] = total def viewMistakes(): mistakesViewLab["text"] = mistakes def viewPercent(): # This calculates the percentage and then rounds it to 2 decimal places..before placing the Percent result on the percentView Label. percentCalc = score/total*100 rounded = round(percentCalc, 2) percentViewLab["text"] = rounded # This keeps the program running. root.mainloop() from tkinter import * import random # GLOBAL VARIABLES # Created with a starting value. answer = 0 score = 0 wrong = 0 mistakes = 0 total = 0 def makeproblem(): # access global answer...this is only required IF you need to update the variable within the function. # this happens below when answer is changed to number1 * number2 global answer # erases all text in current text box. txt.delete(0.0, 'end') sentence = "Here is your problem " # example of generating a random number. number1 = random.randint(2,12) number2 = random.randint(2,12) answer = number1 * number2 # creates a justification command called centre. (Not too sure why this is needed here...but not on the answer box elsewhere!) center = txt.tag_config("center", justify="center") txt.insert(0.0, sentence, "center") txt.insert(2.2, number1, "center") txt.insert(3.3, " x ", "center") txt.insert(4.4, number2, "center") def checkanswer(): txt.delete(0.0, 'end') # as each variable changes outside of function...we need to make these global. global score global mistakes global total # checks for what is written in answerbox using the 'get' feature...makes it an integer. response = int(answerbox.get()) wordScore = "Your score is now " if response == answer: score += 1 total += 1 result = "Great Job! " root.update() viewSC() viewPercent() viewTotal() else : total += 1 result = "Sorry...you made a mistake. \n " # the \n above adds a line break. mistakes += 1 viewMistakes() viewTotal() viewPercent() center = txt.tag_config("center", justify="center") txt.insert(0.0, result, "center") txt.insert(3.0, wordScore, "center") txt.insert(8.1, score, "center") # txt.insert(1,1, "Score is") #txt.insert(3,3, score) def about(): txt.delete(0.0, 'end') instructions = "Here is how you play the game. Press generate problem..and then enter your answer. Your score will be displayed below." txt.insert(0.0,instructions) root = Tk() root.geometry("640x700+0+0") root.title("Times Tables Game") # MENU SECTION # These are included as an example menu structure...in many cases they don't do much...but do feature instructions and a quit feature. # create a toplevel menu menubar = Menu(root) # Just an example of printing hello to console for use in a menu item. def hello(): print ("hello!") # display the menu root.config(menu=menubar) # create a pulldown menu, and adds it to the menu bar filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Open", command=makeproblem) filemenu.add_command(label="Save", command=makeproblem) filemenu.add_separator() filemenu.add_command(label="Exit", command=root.quit) menubar.add_cascade(label="File", menu=filemenu) # create more pulldown menus editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label="Cut", command=checkanswer) editmenu.add_command(label="Copy", command=checkanswer) editmenu.add_command(label="Paste", command=checkanswer) menubar.add_cascade(label="Edit", menu=editmenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="About", command=about) menubar.add_command(label="Hello", command=hello) menubar.add_cascade(label="Help", menu=helpmenu) menubar.add_command(label="Quit", command=root.quit) # Plain text labels at top of window. timeslabel = Label(root, text="Times Tables Practice", fg="white", bg="blue", font=("arial", 36, "bold")) timeslabel.grid(columnspan=12, sticky='ew') instruction = Label(root, text="Please click on the button to generate a problem", fg="blue", bg="white", font=("arial", 16, "bold")) instruction.grid(row=2, columnspan=20) # Makes an entry box with the variable of 'answerbox' answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify ="center") answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) # Makes a button that generate the Times Tables problem btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", command=makeproblem) btn.grid(row=11, columnspan=2, sticky=EW) # Makes a button that checks the answer btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", command=checkanswer) btn.grid(row=13, columnspan=2, sticky=EW) #TEXT BOX AREA #This important command creates the text box called 'txt'. This is used for all the text output. txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 20, "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) #Adds a blankline below answer box...but leaves top alignment alone. You could use PAD...but that command does both sides. There may be another way to achieve this. blankline3 = Label(root, text = "", bg = "white") blankline3.grid(row=17, sticky='ew') # SCORING LABELS AND RESULTS SECTION # Places the labels and the results beside each other in column 0 and column 1. # Note: Each 'View' label grabs the starting score from the declarations at the top. eg. score = 0 scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial", 20, "bold")) scorelab.grid(row=18, column=0, sticky=E) scoreViewLab = Label(root, text=score, fg="black", bg="grey", font=("arial", 20, "bold")) scoreViewLab.grid(row=18, column=1, sticky=W) totalLab = Label(root, text="Out of", bg="purple", fg="white", font=("arial", 20, "bold")) totalLab.grid(row=19, column=0, sticky=E) totalViewLab = Label(root, text=total, fg="black", bg="grey", font=("arial", 20, "bold")) totalViewLab.grid(row=19, column=1, sticky=W) mistakeslab = Label(root, text="Mistakes", bg="red", fg="white", font=("arial", 20, "bold")) mistakeslab.grid(row=20, column=0, sticky=E) mistakesViewLab = Label(root, text=mistakes, fg="black", bg="grey", font=("arial", 20, "bold")) mistakesViewLab.grid(row=20, column=1, sticky=W) percentlab = Label(root, text="Percentage", bg="aqua", fg="white", font=("arial", 20, "bold")) percentlab.grid(row=21, column=0, sticky=E) percentViewLab = Label(root, text=0, fg="black", bg="grey", font=("arial", 20, "bold")) percentViewLab.grid(row=21, column=1, sticky=W) #SCORE UPDATE SECTION. # Each of these functions allows the 4 scoring labels to be updated as answers are deemed correct or incorrect with the if/else statement. # The viewPercent function includes the calculation to update the percentView label...shows an example of a calculation within a label. def viewSC(): scoreViewLab["text"] = score def viewTotal(): totalViewLab["text"] = total def viewMistakes(): mistakesViewLab["text"] = mistakes def viewPercent(): percentViewLab["text"] = score/total*100 # This keeps the program running. root.mainloop() Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Thu, Aug 16, 2018 at 7:11 PM, Alan Gauld via Tutor wrote: > On 16/08/18 08:18, Matthew Polack wrote: > > > The last remaining issue is the program does not calculate the percentage > > right when you make mistakes...it just keeps giving a result of 100%. > > > def percentCheck(): > > global percentScore > > global score > > global mistakes > > global total > > While you do need some globals in your program you only > need to declare the ones you are changing. In this case > you only need to declare percentScore as global. > > > percentScore = float(score/total) * 100 > > To debug this I would add a print line such as > > print(score, total) > > Since if you always get 100 it suggests that score > and total are the same. > > One problem here is that you are converting to float > after doing the division. That's usually the wrong > thing to do. In fact I notice you do that a lot of > conversions on expressions. Its much safer to do the > conversions on the individual values then perform > the computation after the conversion. > > In fact in this case (and most of the other similar > cases) you should not need the float conversion since > you already converted the values when you read them > from the GUI. You should aim to convert the data > into the correct type as soon as possible then you > will not need to use conversions anywhere else. > > Some more observations below... > > > viewPercent() > > > > > > def makeproblem(): > > # deletes anything in text box from location 00 to the end > > global answer # access global answer > > > > txt.delete(0.0, 'end') > > > > sentence = "Here is your problem " > > > > number1 = random.randint(2,12) > > number2 = random.randint(2,12) > > > > answer = number1 * number2 > > > > txt.insert(0.0, sentence) > > txt.insert(2.2, number1) > > txt.insert(3.3, " x ") > > txt.insert(4.4, number2) > > > > def checkanswer(): > > # deletes anything in text box from location 00 to the end > > txt.delete(0.0, 'end') > > > > global answer > > global score > > global wrong > > global mistakes > > global percentScore > > global total > > > > # checks for what is written in answerbox > > response = int(answerbox.get()) > > wordScore = "Your score is now " > > > > if response == answer: > > score = int(score + 1) > > total = int(total + 1) > .... > > else : > > score= int(score + 1) > > total = int(total + 1) > > Notice that regardless of what the answer is > you update both score and total. And again you > don't need the int() conversions, the variables > are already integers. > > > root = Tk() > > root.geometry("640x700+0+0") > > root.title("Times Tables") > > > > > > #HOW CAN I CENTRE THE TEXT??? > > txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 24, > "bold")) > > txt.grid(row=12, columnspan=2, sticky=EW ) > > AS per Peter's link you need to create a tag and configure > it with the font and justification you want. Then when you > insert the text you add the tag name. > > eg: > > center = txt.tag_config("center", justify="center") > txt.insert(1.0, "Hello world", "center") > > > > blankline3 = Label(root, text = "", bg = "white") > > blankline3.grid(row=17, sticky='ew') > > I'm not sure what this is for. If you want some space > just add some padding to the label below. > > > scorelab = Label(root, text="Score", bg="green", fg="white", > font=("arial", > > 20, "bold")) > > scorelab.grid(row=18, column=0, sticky=E) > > Note that you create a Label here, but in ViewSC below you create > another label which causes this one to be deleted. This is not > necessary, instead just change the text of this label in viewSC. > > scorelab['text'] = "New text here" > > > totalLab = Label(root, text="Out of", bg="purple", fg="white", > > font=("arial", 20, "bold")) > > totalLab.grid(row=19, column=0, sticky=E) > > Same applies to the other viewXXX functions, just update these > labels, don't build and destroy new label widgets each time. > That's a lot of wasted work and time for your PC. > > > def viewSC(): > > global score > > You don't change score so no need for global here. > You only need global when changing the data. > > > scoreViewLab = Label(root, text=score, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > scoreViewLab.grid(row=18, column=1, sticky=W) > > I just noticed this is in a different grid location, > but the principle still applies create it once at the > start of the GUI then update it in the view functions. > > > def viewTotal(): > > global total > > #scoreViewLab=Label(root, scoreView, textvariable=scoreView) > > totalViewLab = Label(root, text=total, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > totalViewLab.grid(row=19, column=1, sticky=W) > > > > def viewWrong(): > > global wrong > > global mistakes > > > > #scoreViewLab=Label(root, scoreView, textvariable=scoreView) > > wrongViewLab = Label(root, text=mistakes, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > wrongViewLab.grid(row=20, column=1, sticky=W) > > You declare wrong as global but never use it. > Should this function not be called viewMistakes? > > > def viewPercent(): > > global percentScore > > global total > > global score > > #scoreViewLab=Label(root, scoreView, textvariable=scoreView) > > percentViewLab = Label(root, text=percentScore, fg="black", > bg="grey", > > font=("arial", 20, "bold")) > > percentViewLab.grid(row=21, column=1, sticky=W) > > > viewSC() > > viewWrong() > > viewPercent() > > viewTotal() > > > > root.mainloop( > While your code sort of works its doing an awful > lot of work that it doesn't need to do. You need > to stop and think through why you use each global > and type conversions and only keep the ones you > really need. > > Similarly you should only need to create the > widgets once when you build the GUI. After that > its just a matter of updating the content. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From matthew.polack at htlc.vic.edu.au Fri Aug 17 00:40:52 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Fri, 17 Aug 2018 14:40:52 +1000 Subject: [Tutor] Recommended way for end users to run our Python programs? Message-ID: Hi, We're enjoying learning Python in our school...but I have a question regarding the way the end users should ideally run the software. Does this always require Python being installed as a full language on the end users computer? ie. At the moment we install Python...add it to the path in Windows...develop and run the software we make...workable for the developer.....but a bit of mucking around for someone who goes to use our programs. Is there some other way to get it working in either a browser...or as a 'self contained' windows app ...or an Android/IOS app....or a regular Windows .exe file to install? Just trying to get my head around the 'end game' of all this? Thanks, Matt If we make a python.py program and want people on Windows to run it...does this mean there must be Python installed on that computer in order to run it. Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From alan.gauld at yahoo.co.uk Fri Aug 17 04:50:35 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 17 Aug 2018 09:50:35 +0100 Subject: [Tutor] Recommended way for end users to run our Python programs? In-Reply-To: References: Message-ID: On 17/08/18 05:40, Matthew Polack wrote: > Does this always require Python being installed as a full language on the > end users computer? No. It does require the Python interpreter plus any modules you write or use(including any modules your modules use...) There are a few tools around that can collect this information and build an executable "exe" file that bundles everything together for convenience. py2exe being the best known. The downside of this is that if you install several such programs you wind up installing multiple copies of Python which is a bit of a waste of space - but disk space is cheap nowadays... > Is there some other way to get it working in either a browser...or as a > 'self contained' windows app ...or an Android/IOS app....or a regular > Windows .exe file to install? For Android there is a toolset called Kivvy that some have used successfully. Personally I use the QPython IDE on Android but it only supports CLI programs, no GUI. (I think it can run Kivvy code too) I have no idea about Python on iOS... On the other hand requiring Python on the target platform is not such an unusual thing. For many years VisualBasic programs required a VBRUN.DLL to be installed. And Java programs require the JVM to be in place. So you can just build a Windows installer that checks if Python is already there and if not installs Python and then adds your code. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Fri Aug 17 05:15:36 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 17 Aug 2018 10:15:36 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 17/08/18 03:19, Matthew Polack wrote: > 1.) Centre feature > > When I use txt.insert I need to use the feature Peter found... > > center = txt.tag_config("center", justify="center") > txt.insert(0.0, result, "center") > > but in the Enter label section...I could just use it straight away..without > defining it with the tag... > > answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify > ="center") > answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) > > Can you explain why? That's how the Tcl/Tlk designers decided to do things. tags are a concept that only apply to the Text widget so don't make much sense in a single line Entry. But essentially its an arbitrary design decision taken 30 years ago and we are stuck with it :-) > 2.) When inserting the wording re: 'You have made mistake' or 'Great job' > etc...I found I had to break it up into separate lines...as I was getting > syntax errors. > > txt.insert(0.0, result, "center") > txt.insert(3.0, wordScore, "center") > txt.insert(8.1, score, "center") > > > Is there a way to simply combine all these commands with one txt.insert and > using commas? Not with commas but you can use line breaks inside a triple quoted string and just do a single insert. In fact one of the improvements I'd suggest for your code is to use string formatting to insert the values into your strings before inserting them. eg: fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" % answer,score txt.insert(1.0, fail_str, "center") > 3.) Is there anything else in this code that looks like a bit of a > glaring...'Coding Rookie' mistake? Or is simply inefficient? I'll send a second reply with inline comments. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Fri Aug 17 06:18:18 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 17 Aug 2018 11:18:18 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 17/08/18 03:19, Matthew Polack wrote: > def viewPercent(): > percentCalc = score/total*100 > rounded = round(percentCalc, 2) > percentViewLab["text"] = rounded Since you only want the rounded value for display this is usually achieved using string formatting: >>> s = "Here is a string with a rounded float: %.2f" % 42.3456789 >>> s 'Here is a string with a rounded float: 42.35' That doesn't change the value of the variable but changes how it is displayed. There are lots of other options in format strings to control justification, padding etc. You should definitely explore their capabilities. Just because you are using a GUI rather than a console doesn't mean the string methods are any less useful. > from tkinter import * > import random > > # GLOBAL VARIABLES > # Created with a starting value. > answer = 0 > score = 0 > wrong = 0 > mistakes = 0 > total = 0 > > def makeproblem(): > global answer > > txt.delete(0.0, 'end') > sentence = "Here is your problem " > number1 = random.randint(2,12) > number2 = random.randint(2,12) > answer = number1 * number2 > > center = txt.tag_config("center", justify="center") > > txt.insert(0.0, sentence, "center") > txt.insert(2.2, number1, "center") > txt.insert(3.3, " x ", "center") > txt.insert(4.4, number2, "center") All of the above could be replaced with a single format string and a single insert. display = """ Here is your problem: %d x %d """ % (number1, number2) txt.insert(1.0,display, "center") > def checkanswer(): > txt.delete(0.0, 'end') > > global score > global mistakes > global total Its conventional (although not necessary) to put all globals at the very top of the function. > response = int(answerbox.get()) > wordScore = "Your score is now " > if response == answer: > score += 1 > total += 1 > result = "Great Job! " > root.update() > viewSC() > viewPercent() > viewTotal() > else : > total += 1 > result = "Sorry...you made a mistake. \n " > # the \n above adds a line break. > mistakes += 1 > viewMistakes() > viewTotal() > viewPercent() Notice you display Total and Percent in both block but do it in an inconsistent order. If you took both of this display calls outside the if/else you only need to call them once and they will be in the same sequence for all cases. > center = txt.tag_config("center", justify="center") > txt.insert(0.0, result, "center") > txt.insert(3.0, wordScore, "center") > txt.insert(8.1, score, "center") > # txt.insert(1,1, "Score is") > #txt.insert(3,3, score) Again this could all be replaced with string formatting and a single insert() > def about(): > txt.delete(0.0, 'end') > > instructions = "Here is how you play the game. Press generate > problem..and then enter your answer. Your score will be displayed below." If you use triple quoted strings you can have more text and lay it out using line breaks etc. > txt.insert(0.0,instructions) > root = Tk() > root.geometry("640x700+0+0") > root.title("Times Tables Game") > > # MENU SECTION > # These are included as an example menu structure...in many cases they > don't do much...but do feature instructions and a quit feature. > > # create a toplevel menu > menubar = Menu(root) > > # Just an example of printing hello to console for use in a menu item. > def hello(): > print ("hello!") > > # display the menu > root.config(menu=menubar) > > # create a pulldown menu, and adds it to the menu bar > filemenu = Menu(menubar, tearoff=0) > filemenu.add_command(label="Open", command=makeproblem) > filemenu.add_command(label="Save", command=makeproblem) > filemenu.add_separator() > filemenu.add_command(label="Exit", command=root.quit) > > menubar.add_cascade(label="File", menu=filemenu) > > # create more pulldown menus > editmenu = Menu(menubar, tearoff=0) > editmenu.add_command(label="Cut", command=checkanswer) > editmenu.add_command(label="Copy", command=checkanswer) > editmenu.add_command(label="Paste", command=checkanswer) > menubar.add_cascade(label="Edit", menu=editmenu) > > helpmenu = Menu(menubar, tearoff=0) > helpmenu.add_command(label="About", command=about) > menubar.add_command(label="Hello", command=hello) > menubar.add_cascade(label="Help", menu=helpmenu) > menubar.add_command(label="Quit", command=root.quit) A bit odd adding a command after you add the cascade. Normally we do the cascade as the last item. > # Plain text labels at top of window. > timeslabel = Label(root, text="Times Tables Practice", fg="white", > bg="blue", font=("arial", 36, "bold")) > timeslabel.grid(columnspan=12, sticky='ew') > instruction = Label(root, text="Please click on the button to generate a > problem", fg="blue", bg="white", font=("arial", 16, "bold")) > instruction.grid(row=2, columnspan=20) > > # Makes an entry box with the variable of 'answerbox' > answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify > ="center") > answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) > > # Makes a button that generate the Times Tables problem > btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", > command=makeproblem) > btn.grid(row=11, columnspan=2, sticky=EW) > > # Makes a button that checks the answer > btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", > command=checkanswer) > btn.grid(row=13, columnspan=2, sticky=EW) > > #TEXT BOX AREA > #This important command creates the text box called 'txt'. This is used for > all the text output. > txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 20, "bold")) > txt.grid(row=12, columnspan=2, sticky=EW ) An interesting future option might be to eliminate this text box and put it in a dialog (along with the result labels) that would open to display the results in a separate window... Consider it homework :-) > #Adds a blankline below answer box...but leaves top alignment alone. You > could use PAD...but that command does both sides. There may be another way > to achieve this. You can do it in various ways including putting a label in a frame and then anchoring the label to the bottom of the frame... But an empty label will suffice here. Only GUI purists would object. The easiest way is probably just to insert a '\n' newline character at the start of the label text. > blankline3 = Label(root, text = "", bg = "white") > blankline3.grid(row=17, sticky='ew') > > # SCORING LABELS AND RESULTS SECTION > # Places the labels and the results beside each other in column 0 and > column 1. > # Note: Each 'View' label grabs the starting score from the declarations at > the top. eg. score = 0 > scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial", > 20, "bold")) > scorelab.grid(row=18, column=0, sticky=E) > > scoreViewLab = Label(root, text=score, fg="black", bg="grey", > font=("arial", 20, "bold")) > scoreViewLab.grid(row=18, column=1, sticky=W) > > totalLab = Label(root, text="Out of", bg="purple", fg="white", > font=("arial", 20, "bold")) > totalLab.grid(row=19, column=0, sticky=E) > > totalViewLab = Label(root, text=total, fg="black", bg="grey", > font=("arial", 20, "bold")) > totalViewLab.grid(row=19, column=1, sticky=W) > > mistakeslab = Label(root, text="Mistakes", bg="red", fg="white", > font=("arial", 20, "bold")) > mistakeslab.grid(row=20, column=0, sticky=E) > > mistakesViewLab = Label(root, text=mistakes, fg="black", bg="grey", > font=("arial", 20, "bold")) > mistakesViewLab.grid(row=20, column=1, sticky=W) > > percentlab = Label(root, text="Percentage", bg="aqua", fg="white", > font=("arial", 20, "bold")) > percentlab.grid(row=21, column=0, sticky=E) > > > percentViewLab = Label(root, text=0, fg="black", bg="grey", font=("arial", > 20, "bold")) > percentViewLab.grid(row=21, column=1, sticky=W) > > > #SCORE UPDATE SECTION. > def viewSC(): > scoreViewLab["text"] = score > > def viewTotal(): > totalViewLab["text"] = total > > def viewMistakes(): > mistakesViewLab["text"] = mistakes > > def viewPercent(): > percentViewLab["text"] = rounded You could replace all of these with a single function: def update_label(label,text): label['text'] = text And supply change the calls from, for example: viewTotal() to update_label(totalViewLab, total) And you then need a function to calculate the percent value: def percent_string(score, total): return ".2f" % (score/total *100) And you can now eliminate the percent global variable and call update_label with: update_label(percentViewLab, percent_string(score, total)) ##### Additional teachers notes #### As a general comment while you can use globals for everything it considered bad practice. You should strive to minimise use of global variables (google global variables for lots of discussion about why). Its generally considered better to make your functions as independent as possible so that they take in values via parameters and return a single value (occasionally a tuple). As an example: # global var value = 42 # define a function def double(val): return val * 2 # Now call it value = double(value) So here we have not had to use the global keyword but our function reads the global variable as input and returns a new value which we assign to it. This relies on another good practice for functions namely to keep them small and only do a single task. If you find a single function updating lots of global variables that often indicates that you should have more than one function. In particular we try to separate display from calculation. So in your case the check answer function should really only check the answer and set a success or failure flag. You can then have a display result function that checks the flag and updates all the labels and text. Normally, I wouldn't highlight these issue to a beginner but since you are also a teacher I felt that you should be aware. They cross the boundary from pure coding to software design. Your code as it stands is acceptable for a beginner but in a year you will probably look at it and cringe slightly... But that is true with any new coding venture. :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Sun Aug 19 09:01:18 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 19 Aug 2018 14:01:18 +0100 Subject: [Tutor] Recommended way for end users to run our Python programs? In-Reply-To: References: Message-ID: On 19/08/18 12:11, Abdur-Rahmaan Janhangeer wrote: > btw qpython supports sl4a since long > > maybe you meant : "no packaged options" Never heard of sl4a, ... OK I did a search. Its a scripting interface to the Android API that supports Python. It looks interesting, next time I have a spare week I'll need to investigate in more detail. Thanks for the pointer. What I meant was that the OPs Tkinter program wouldn't work on Android (or any of the other "standard" Python GUI toolkits). -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From arj.python at gmail.com Sun Aug 19 07:11:49 2018 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Sun, 19 Aug 2018 15:11:49 +0400 Subject: [Tutor] Recommended way for end users to run our Python programs? In-Reply-To: References: Message-ID: btw qpython supports sl4a since long maybe you meant : "no packaged options" Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius On Fri, 17 Aug 2018, 12:50 Alan Gauld via Tutor, wrote: > On 17/08/18 05:40, Matthew Polack wrote: > > > Does this always require Python being installed as a full language on the > > end users computer? > > No. It does require the Python interpreter plus any modules > you write or use(including any modules your modules use...) > > There are a few tools around that can collect this information > and build an executable "exe" file that bundles everything > together for convenience. py2exe being the best known. > > The downside of this is that if you install several such > programs you wind up installing multiple copies of Python > which is a bit of a waste of space - but disk space is > cheap nowadays... > > > Is there some other way to get it working in either a browser...or as a > > 'self contained' windows app ...or an Android/IOS app....or a regular > > Windows .exe file to install? > > For Android there is a toolset called Kivvy that some have used > successfully. Personally I use the QPython IDE on Android but > it only supports CLI programs, no GUI. (I think it can run > Kivvy code too) > > I have no idea about Python on iOS... > > On the other hand requiring Python on the target platform is > not such an unusual thing. For many years VisualBasic programs > required a VBRUN.DLL to be installed. And Java programs require > the JVM to be in place. So you can just build a Windows > installer that checks if Python is already there and if > not installs Python and then adds your code. > > HTH > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From arj.python at gmail.com Sun Aug 19 09:05:00 2018 From: arj.python at gmail.com (Abdur-Rahmaan Janhangeer) Date: Sun, 19 Aug 2018 17:05:00 +0400 Subject: [Tutor] Recommended way for end users to run our Python programs? In-Reply-To: References: Message-ID: https://play.google.com/store/apps/details?id=ru.iiec.pydroid3 that one also supports kivy, tkinter on android last time i checked py android support i agree is more than lacking Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius On Sun, 19 Aug 2018, 17:01 Alan Gauld, wrote: > On 19/08/18 12:11, Abdur-Rahmaan Janhangeer wrote: > > btw qpython supports sl4a since long > > > > maybe you meant : "no packaged options" > > Never heard of sl4a, ... OK I did a search. > Its a scripting interface to the Android API that > supports Python. > > It looks interesting, next time I have a spare week > I'll need to investigate in more detail. Thanks for the > pointer. > > What I meant was that the OPs Tkinter program wouldn't > work on Android (or any of the other "standard" Python > GUI toolkits). > > -- > > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > From renegadesgt at gmail.com Tue Aug 21 07:16:35 2018 From: renegadesgt at gmail.com (Jacob Braig) Date: Tue, 21 Aug 2018 05:16:35 -0600 Subject: [Tutor] Question Message-ID: I am just starting out coding and decided on python. I am confused with something I go shooting a lot so i wanted to make some stupid easy calculator for ammo and slowly build the program up when I understand python better but the code I have now keeps popping up an error and I don't understand where i went wrong a little help please. Here is the code like I said very simple stuff. """ This is a simple program for ammo calculation. Created by Jacob """ AMMO = " This is how much ammo remains for .40 pistol %s. " print "Program has started." ammopistol = raw_input("Enter total ammo before use. ") ammopused = raw_input("Enter total ammo used. ") ammopleft = ammopistol - ammopused print AMMO % (ammopistol, ammopused,) ammoleft I am having issues with " ammopleft = ammopistol - ammopused " any idea where I have gone wrong? From timomlists at gmail.com Tue Aug 21 09:30:43 2018 From: timomlists at gmail.com (Timo) Date: Tue, 21 Aug 2018 15:30:43 +0200 Subject: [Tutor] Question In-Reply-To: References: Message-ID: <201d0524-23a0-6649-7838-0e40671afd2d@gmail.com> Op 21-08-18 om 13:16 schreef Jacob Braig: > I am just starting out coding and decided on python. I am confused with > something I go shooting a lot so i wanted to make some stupid easy > calculator for ammo and slowly build the program up when I understand > python better but the code I have now keeps popping up an error and I don't > understand where i went wrong a little help please. > Here is the code like I said very simple stuff. > > """ > This is a simple program for ammo calculation. > Created by Jacob > """ > AMMO = " This is how much ammo remains for .40 pistol %s. " > > print "Program has started." > > ammopistol = raw_input("Enter total ammo before use. ") > ammopused = raw_input("Enter total ammo used. ") > ammopleft = ammopistol - ammopused > > print AMMO % (ammopistol, ammopused,) ammoleft > > I am having issues with " ammopleft = ammopistol - ammopused " any idea > where I have gone wrong? Always include the full traceback (error message). The problem is that raw_input() returns a string, so you are doing something like "10" - "2" instead of 10 - 2 for example. The error message should have told you so: ??? TypeError: unsupported operand type(s) for -: 'str' and 'str' The solution is to cast these inputs to integers, either directly during input: ??? ammopistol = int(raw_input("Enter total ammo before use. ")) ??? ammopused = int(raw_input("Enter total ammo used. ")) Or during calculation: ??? ammopleft = int(ammopistol) - int(ammopused) Next issue will be your print statement. See the following website on how to properly format strings: https://pyformat.info/ > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From steve at pearwood.info Tue Aug 21 09:38:02 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 21 Aug 2018 23:38:02 +1000 Subject: [Tutor] Question In-Reply-To: References: Message-ID: <20180821133802.GC24160@ando.pearwood.info> On Tue, Aug 21, 2018 at 05:16:35AM -0600, Jacob Braig wrote: > I am having issues with " ammopleft = ammopistol - ammopused " any idea > where I have gone wrong? What sort of issues? Should we try to guess, or would you like to tell us? I'm reminded of a joke... A man goes to the doctor. Doctor: "So what seems to be the problem?" Man: "You're the doctor, you tell me." -- Steve From glennmschultz at me.com Tue Aug 21 09:10:52 2018 From: glennmschultz at me.com (Glenn Schultz) Date: Tue, 21 Aug 2018 13:10:52 +0000 (GMT) Subject: [Tutor] Building a Package Message-ID: <5856b8c4-65d5-41a1-8f42-3a200a29fff1@me.com> All, I have a project pthon(3.7) I have followed the python setup instructions. I get a dist folder with the correct files. ?Now, I would like to install locally from my local machine (note I am not using virtual enviroment as our firewall does not allow installation of packages when using VE). ?In my site packages directory I get the foo.dist-info but not foo folder. Using setuptools and following the packaging python project I had to # out over 70% of the example setup as they were all throwing warnings etc. and prohibiting the final build. ? Is there an alternative source to guide one through project packaging? Its now been two-days of struggle with no success. ? I would like to migrate some of my projects from R to Python. ?But, honestly, packaging a python project seems far more difficult than building an R package. ?I'm not trolling Python vs. R but my God, the level of frustration with python packaging is about to make me walk away. ? Either I am a complete moron or packaging python is a poorly documented nightmare. ?If anyone can point me to source for pyhton packaging that is better than the Packaging Python Projects website I would greatly appreciate the direction. Beyond Frustrated, Glenn From alan.gauld at yahoo.co.uk Tue Aug 21 13:35:58 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 21 Aug 2018 18:35:58 +0100 Subject: [Tutor] Question In-Reply-To: References: Message-ID: On 21/08/18 12:16, Jacob Braig wrote: > I am just starting out coding and decided on python. It looks like you are using Python v2 (maybe v2.7?) but the latest version is 3.7 and for beginners we normally recommend adopting v3. It doesn't change anything much in this case but it saves you relearning too much later if you decide to switch. > python better but the code I have now keeps popping up an error Always include the full error text so we don't need to guess. It contains a lot of useful information. > AMMO = " This is how much ammo remains for .40 pistol %s. " > > print "Program has started." > > ammopistol = raw_input("Enter total ammo before use. ") raw_input() does what it says, it reads the raw characters typed at the keyboard. It does not try to guess what they are - in this case numbers - it just stores them as a character string. You need to convert them to the type of data you need. ammopistol = int( raw_input("Enter total ammo before use. ") ) > ammopused = raw_input("Enter total ammo used. ") same here > ammopleft = ammopistol - ammopused You cannot subtract character strings so you got an error, but once you convert the data it should work. > print AMMO % (ammopistol, ammopused,) ammoleft This won't work however. Your AMMO string has one % placeholder in it so it expects exactly 1 value on the right of the % sign. You are providing a tuple of two values. Then you add a third value that's not in the tuple and is invalid syntax in Python. Python won't know what to do and you will get another error. You really want something like print AMMO % ammoleft HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Tue Aug 21 13:53:13 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 21 Aug 2018 18:53:13 +0100 Subject: [Tutor] Building a Package In-Reply-To: <5856b8c4-65d5-41a1-8f42-3a200a29fff1@me.com> References: <5856b8c4-65d5-41a1-8f42-3a200a29fff1@me.com> Message-ID: On 21/08/18 14:10, Glenn Schultz via Tutor wrote: > Either I am a complete moron or packaging python is a poorly documented nightmare. ? I suspect the latter is true to some extent. To be fair Python packaging was a complete mess for many years with competing technologies and tools. It is only in the last 3 years or so that things have settled down so it wouldn't surprise me if the documentation is still catching up. However, I virtually never build packages so can't really comment, but hopefully somebody else can help. What would be more useful to such a person is if you can send the actual code and error messages, since saying you had to comment out 70% of the lines because of warnings doesn't really tell us very much. It may be that you could safely ignore the warnings or it may indicate a more serious underlying error. But as of now we are just guessing. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From mats at wichmann.us Tue Aug 21 20:22:03 2018 From: mats at wichmann.us (Mats Wichmann) Date: Tue, 21 Aug 2018 18:22:03 -0600 Subject: [Tutor] Building a Package In-Reply-To: References: <5856b8c4-65d5-41a1-8f42-3a200a29fff1@me.com> Message-ID: <760c7450-9dc7-3035-51cf-04279c0021ab@wichmann.us> On 08/21/2018 11:53 AM, Alan Gauld via Tutor wrote: > On 21/08/18 14:10, Glenn Schultz via Tutor wrote: > >> Either I am a complete moron or packaging python is a poorly documented nightmare. ? > > I suspect the latter is true to some extent. > To be fair Python packaging was a complete mess for > many years with competing technologies and tools. > It is only in the last 3 years or so that things > have settled down so it wouldn't surprise me if > the documentation is still catching up. > > However, I virtually never build packages so can't > really comment, but hopefully somebody else can help. > > What would be more useful to such a person is if > you can send the actual code and error messages, > since saying you had to comment out 70% of the > lines because of warnings doesn't really tell us very > much. It may be that you could safely ignore the > warnings or it may indicate a more serious > underlying error. But as of now we are just > guessing. > > I don't think packaging has made anybody really happy for... like... forever. I put this video on my to-watch list when scanning the PyCon material from this year's US event. Haven't watched it yet - maybe this is the prod needed! - but I'm hoping it's a coherent "current state of the art" report. https://www.youtube.com/watch?v=AQsZsgJ30AE From rafael.knuth at gmail.com Wed Aug 22 02:46:11 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Wed, 22 Aug 2018 08:46:11 +0200 Subject: [Tutor] Getting started with Pandas Message-ID: import pandas as pd cities_lst = pd.read_table("cool_cities.csv") cities_lst.head() I was trying to rewrite the above as a function. Unlike my code above, my function below did not return the first 5 rows, but just nothing: def cities(file_name): import pandas as pd cities_lst = pd.read_table(file_name) cities_lst.head() cities("cool_cities.csv") Why does my function not return the first 5 rows? What's the mistake I am making here? From rls4jc at gmail.com Tue Aug 21 18:27:46 2018 From: rls4jc at gmail.com (Roger Lea Scherer) Date: Tue, 21 Aug 2018 15:27:46 -0700 Subject: [Tutor] Accessing a tuple of a dictionary's value Message-ID: So I'm trying to divide fractions, technically I suppose integers. So, for instance, when the user inputs a 1 as the numerator and a 2 as the denominator to get the float 0.5, I want to put the 0.5 as the key in a dictionary and the 1 and the 2 as the values of the key in a list {0.5: [1, 2]}, hoping to access the 1 and 2 later, but not together. I chose a dictionary so the keys won't duplicate. I can't find anything in StackOverflow or Python documentation specifically about this. They talk about accessing a list or a tuple or a dictionary, but not when the value is a tuple or list. I've tried: fractions.values([0]) which gives a TypeError: values() takes no arguments (1 given) I've tried fractions.values()[0] which gives a TypeError: 'dict_values' object does not support indexing Both of these errors sort of make sense to me, but I can't find a way to access the 1 or the 2 in the dictionary key:value pair {0.5: [1, 2]} Thank you for your help. -- Roger Lea Scherer 623.255.7719 *Strengths:* Input, Strategic, Responsibility, Learner, Ideation From giles at coochey.net Wed Aug 22 06:15:02 2018 From: giles at coochey.net (Giles Coochey) Date: Wed, 22 Aug 2018 11:15:02 +0100 Subject: [Tutor] Getting started with Pandas In-Reply-To: References: Message-ID: On 22/08/2018 07:46, Rafael Knuth wrote: > import pandas as pd > cities_lst = pd.read_table("cool_cities.csv") > cities_lst.head() > > I was trying to rewrite the above as a function. > Unlike my code above, my function below did not return the first 5 > rows, but just nothing: > > def cities(file_name): > import pandas as pd > cities_lst = pd.read_table(file_name) > cities_lst.head() try "return cities_lst.head()" rather than just "cities_list.head()" > cities("cool_cities.csv") > > Why does my function not return the first 5 rows? > What's the mistake I am making here? > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From alan.gauld at yahoo.co.uk Wed Aug 22 06:15:42 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 22 Aug 2018 11:15:42 +0100 Subject: [Tutor] Getting started with Pandas In-Reply-To: References: Message-ID: On 22/08/18 07:46, Rafael Knuth wrote: > import pandas as pd > cities_lst = pd.read_table("cool_cities.csv") > cities_lst.head() > > I was trying to rewrite the above as a function. > Unlike my code above, my function below did not return the first 5 > rows, but just nothing: > > def cities(file_name): > import pandas as pd > cities_lst = pd.read_table(file_name) > cities_lst.head() > > cities("cool_cities.csv") > > Why does my function not return the first 5 rows? > What's the mistake I am making here? You are not returning anything. You need to use the return keyword otherwise your function just generates the data internally then throws it away again. def double(x): value = x * 2 # no return statement def treble(x): value = x * 3 return value print(double(4)) -> None print(treble(4)) -> 12 HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Wed Aug 22 06:38:01 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 22 Aug 2018 11:38:01 +0100 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: Message-ID: On 21/08/18 23:27, Roger Lea Scherer wrote: > I can't find anything in StackOverflow or Python documentation specifically > about this. They talk about accessing a list or a tuple or a dictionary, > but not when the value is a tuple or list. The value is irrelevant youi access the value in exactly the same way regardless of data: data = dictionary[key] Now you can access data's elements as normal print(data[0]) Of course you can combine those into a single line: print(dictionary[key][0]) > fractions.values([0]) > which gives a TypeError: values() takes no arguments (1 given) values returns a list(*) of all the values in your dict. In your case a list of tuples. But because it returns all of them it requires no arguments. (*)Not strictly a list, but the v3 implementation of this is a bit weird so we'll ignore the niceties for now! > fractions.values()[0] > which gives a TypeError: 'dict_values' object does not support indexing As per the note it doesn't return a real list (although you can convert it) but that doesn't matter since even if what you are trying worked it would return the first tuple, not the first integer of the tuple. > Both of these errors sort of make sense to me, but I can't find a way to > access the 1 or the 2 in the dictionary key:value pair {0.5: [1, 2]} values[0.5][0] However remember that floats are not exact representations so if you use a calculated value as your key it may not exactly match your given key and it won't find the item! >>> d = {} >>> d[0.3] = (3,10) >>> d[0.3] (3, 10) >>> d[0.1+0.2] Traceback (most recent call last): File "", line 1, in d[0.1+0.2] KeyError: 0.30000000000000004 >>> >>> d[ round(0.1+0.2, 2) ] (3, 10) >>> Just something to be aware of. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From giles.coochey at netsecspec.co.uk Wed Aug 22 06:14:45 2018 From: giles.coochey at netsecspec.co.uk (Giles Coochey) Date: Wed, 22 Aug 2018 11:14:45 +0100 Subject: [Tutor] Getting started with Pandas In-Reply-To: References: Message-ID: <124dc427-76e3-6ea6-63bb-0615e637b933@netsecspec.co.uk> On 22/08/2018 07:46, Rafael Knuth wrote: > import pandas as pd > cities_lst = pd.read_table("cool_cities.csv") > cities_lst.head() > > I was trying to rewrite the above as a function. > Unlike my code above, my function below did not return the first 5 > rows, but just nothing: > > def cities(file_name): > import pandas as pd > cities_lst = pd.read_table(file_name) > cities_lst.head() try "return cities_lst.head()" rather than just "cities_list.head()" > cities("cool_cities.csv") > > Why does my function not return the first 5 rows? > What's the mistake I am making here? > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From rafael.knuth at gmail.com Wed Aug 22 06:29:22 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Wed, 22 Aug 2018 12:29:22 +0200 Subject: [Tutor] Getting started with Pandas In-Reply-To: References: Message-ID: > You are not returning anything. > You need to use the return keyword otherwise your > function just generates the data internally then > throws it away again. ok, got it - thanks. my code below did not require a return statement, hence I was assuming it wouldn't be needed in my function either. import pandas as pd cities_lst = pd.read_table("cool_cities.csv") cities_lst.head() From alan.gauld at yahoo.co.uk Wed Aug 22 06:56:44 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 22 Aug 2018 11:56:44 +0100 Subject: [Tutor] Getting started with Pandas In-Reply-To: References: Message-ID: On 22/08/18 11:29, Rafael Knuth wrote: > my code below did not require a return statement, hence I was assuming > it wouldn't be needed in my function either. return is only used inside a function, it makes no sense outside (and is a syntax error). Its purpose is to return a value to the caller of the function. Any time you want to get a value back from a function you must use return (or the slightly more esoteric 'yield') Otherwise you will receive the default return value of None. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Wed Aug 22 07:35:23 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 22 Aug 2018 21:35:23 +1000 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: Message-ID: <20180822113521.GI24160@ando.pearwood.info> On Tue, Aug 21, 2018 at 03:27:46PM -0700, Roger Lea Scherer wrote: > So I'm trying to divide fractions, technically I suppose integers. Python has a library for doing maths with fractions. Unfortunately it is considerably too complex to use as a learning example, but as a practical library for use, it's great. py> from fractions import Fraction py> a = Fraction(7, 9) py> a * 3 Fraction(7, 3) py> a + 2 Fraction(25, 9) py> a - Fraction(1, 9) Fraction(2, 3) > So, for > instance, when the user inputs a 1 as the numerator and a 2 as the > denominator to get the float 0.5, I want to put the 0.5 as the key in a > dictionary Be careful. Floats are quirky: py> Fraction(1, 3) Fraction(1, 3) but converting from a float reveals something strange: py> Fraction(1/3) Fraction(6004799503160661, 18014398509481984) The problem is that the float generated by 1/3 is *not* equal to the mathematical fraction 1 over 3. Computer floats have only a finite precision, in the case of Python 64 bits. Fractions which are repeating in binary cannot be represented as an exact float. So the mathematically precise number 1/3 looks like this is decimal: 0.33333333... # need an infinite number of 3s and like this in binary (base two): 0.01010101... # need an infinite number of 01s Since that would take an infinite amount of memory, it is impossible to store 1/3 as a floating point number. The closest we get in Python is 0.01010101010101010101010101010101010101010101010101 (binary) which is precisely and exactly equal to 6004799503160661/18014398509481984 rather than 1/3. The bottom line is this: if you try working with floats in this way, you're likely to get surprised from time to time. See here for more detail: https://docs.python.org/3/faq/design.html#why-are-floating-point-calculations-so-inaccurate More to follow in a second response. -- Steve From steve at pearwood.info Wed Aug 22 07:45:16 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 22 Aug 2018 21:45:16 +1000 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: Message-ID: <20180822114516.GJ24160@ando.pearwood.info> On Tue, Aug 21, 2018 at 03:27:46PM -0700, Roger Lea Scherer wrote: > I want to put the 0.5 as the key in a > dictionary and the 1 and the 2 as the values of the key in a list {0.5: [1, > 2]}, hoping to access the 1 and 2 later, but not together. Let's do some experimentation. Here's a list: py> L = [11, 23] py> print(L[0]) # get the first item 11 py> print(L[1]) # get the second item 23 (Yes, I know that its funny that Python counts from 0, so the second item is at index 1...) That syntax works no matter where the list L comes from. Let's put it in a dict: py> D = {11/23: [11, 23]} py> print(D) {0.4782608695652174: [11, 23]} Now let's try retrieving it: py> print(D[11/23]) [11, 23] So where we said "L" before, we can say "D[11/23]" now: py> print(L[1]) 23 py> print(D[11/23][1]) 23 But if you're going to do this, I think fractions are nicer. py> from fractions import Fraction py> x = Fraction(11, 23) py> x.numerator 11 py> x.denominator 23 py> float(x) 0.4782608695652174 -- Steve From jgledhill at protonmail.com Wed Aug 22 10:45:38 2018 From: jgledhill at protonmail.com (JGledhill) Date: Wed, 22 Aug 2018 14:45:38 +0000 Subject: [Tutor] Next step in learning programming with Python Message-ID: Greetings, I am at a point where I am familiar with variables, "if", "while", "for", statements etc, as well as the basics of object oriented programming. Up to this point I've mostly been following tutorials, which involves a lot of hand holding. I'm at the point where I want to actually start "programming", and solving problems by thinking through them, not just copying code examples. Any recommendations on how I can break free? My biggest fear is that I'm going to try to tackle a project out of my depth and end up stuck and frustrated. From alan.gauld at yahoo.co.uk Wed Aug 22 11:32:36 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 22 Aug 2018 16:32:36 +0100 Subject: [Tutor] Next step in learning programming with Python In-Reply-To: References: Message-ID: On 22/08/18 15:45, JGledhill via Tutor wrote: > I'm at the point where I want to actually start "programming",> and solving problems by thinking through them, not just copying code examples. Well done, it's good to recognise that stage in your development. > Any recommendations on how I can break free? > My biggest fear is that I'm going to try to tackle a project out of my depth Start with something simple. I usually suggest a simple utility to automate a task you do on your computer - file renaming or archiving for example. Alternatively try a simple game. OXO (aka tic-tac-toe) is a good example since you need to think about how to represent the board and how to determine win/loss/draw conditions. It's good to start with a console based version first. Once you have that working redo it using a GUI (or Web solution). Although you might find learning GUI/Web programming is a big learning exercise in its own right, in which case miss this out for now. Ask yourself how much of the original solution was used in the second and how much had to be rewritten or modified? Could you have reused more if you'd designed it differently? Rewrite the code so that you have both versions with maximum code sharing between them (ie create a module of functions). (This process of rewriting working code to tidy it up is known as refactoring by professionals) ] Having done that try Conway's 'Game of Life'. It's fully automated but with more complex game play. But shares some of the same basic layout issues etc. Are there opportunities for reuse between your OXO game and Life? Life in particular can add elements of OOP to your coding. Those two exercises should be within your powers and still be a challenge that will make you learn new aspects of what you thought you already knew.. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From mats at wichmann.us Wed Aug 22 12:27:26 2018 From: mats at wichmann.us (Mats Wichmann) Date: Wed, 22 Aug 2018 10:27:26 -0600 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: Message-ID: <9b9d6b2e-ade1-9ebf-39bb-388a110d748f@wichmann.us> On 08/21/2018 04:27 PM, Roger Lea Scherer wrote: > So I'm trying to divide fractions, technically I suppose integers. So, for > instance, when the user inputs a 1 as the numerator and a 2 as the > denominator to get the float 0.5, I want to put the 0.5 as the key in a > dictionary and the 1 and the 2 as the values of the key in a list {0.5: [1, > 2]}, hoping to access the 1 and 2 later, but not together. I chose a > dictionary so the keys won't duplicate. ... > Both of these errors sort of make sense to me, but I can't find a way to > access the 1 or the 2 in the dictionary key:value pair {0.5: [1, 2]} To add a little bit to the discussion that has already taken place: I'm really unfond of accessing members of a collection by numeric index. Perhaps unreasonably so! It always makes you stop and think when you swing back and look at code later. foo[1]? what was that second element again? Fortunately, Python will let you "unpack" a tuple or list at assignment time, where you provide a number of variables on the left hand side that is equal to the length of the tuple on the right hand side. Setting aside the floating point consideration here by using a string instead, let's say we have a dictionary with two keys, which have a value which is a tuple as you've described it, numerator and demoninator: >>> d = {"half": (1, 2), "twothirds": (2, 3)} you fetch the value by indexing by key, like d["twothirds"] when doing so, you can immediately assign the value to variables that have meaning to you, like this: >>> numer, denom = d["twothirds"] >>> print(numer, denom) (2, 3) I think that's nicer than: numer = d["twothirds][0] From alan.gauld at yahoo.co.uk Wed Aug 22 17:55:22 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 22 Aug 2018 22:55:22 +0100 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: <9b9d6b2e-ade1-9ebf-39bb-388a110d748f@wichmann.us> References: <9b9d6b2e-ade1-9ebf-39bb-388a110d748f@wichmann.us> Message-ID: On 22/08/18 17:27, Mats Wichmann wrote: > I'm really unfond of accessing members of a collection by numeric index. > > >>> numer, denom = d["twothirds"] > >>> print(numer, denom) > (2, 3) > > I think that's nicer than: numer = d["twothirds][0] You can alsao avoid indexes with the namedtuple class in the collections module: >>> import collections as coll >>> frac = coll.namedtuple("Fraction", ['num','den']) >>> frac >>> f = frac(2,3) >>> f.num 2 >>> f.den 3 >>> fracs = {0.67:f} >>> fracs[0.67].num 2 >>> Or just use a nested dictionary: fracs = {0.67, {'num':2, 'den':3}} print( fracs[0.67]['num'] ) But you have the inconvenience of quoting the field names. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From oscar.j.benjamin at gmail.com Wed Aug 22 19:32:12 2018 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Thu, 23 Aug 2018 00:32:12 +0100 Subject: [Tutor] Recommended way for end users to run our Python programs? In-Reply-To: References: Message-ID: On Fri, 17 Aug 2018 at 09:38, Matthew Polack wrote: > > We're enjoying learning Python in our school...but I have a question > regarding the way the end users should ideally run the software. > > Does this always require Python being installed as a full language on the > end users computer? It's certainly easiest for you as the "distributor" of the code if your users already have Python installed or if it is reasonable to ask them to install it. Then you can distribute your code as a single Python .py file or as a .zip file that they should extract or even as a .pyz zip file that can be run directly with Python: https://docs.python.org/3/library/zipapp.html With the .py script or the .pyz zip file it should be possible (assuming that Python is installed in the normal way) for a user to receive the file from you and simply double-click it from the file browser. Another option is to upload your program to PyPI (the app store for Python programmers): https://pypi.org/ Then anyone who has Python installed could install the program using pip from the command line: $ pip install matts_app > ie. At the moment we install Python...add it to the path in > Windows...develop and run the software we make...workable for the > developer.....but a bit of mucking around for someone who goes to use our > programs. As you say installing (and correctly configuring) Python can be too much to ask for some users. In this case there are two broad approaches that you as a distributor of code can take. Both involve providing Python as part of what you provide to your users. The first approach is to make an installer for your program. The users who install your program will then download/receive the installer from you and run it to install the program. Your installer can then be set up to also install a private version of Python just to be used for your program. I don't know of a simple way of doing this but this is probably the approach that would be taken by well-known end-user software that happens to use Python under the hood. As an example the Dropbox software that you may use on your computer is written in Python and provides an installer that bundles Python like this. The second approach which is probably more common for someone in your situation (small development resources and a small number of non-technical end-users) is to create an .exe-like file that combines both the Python interpreter and your program together. There are many tools for doing this. Alan already mentioned py2exe, I have personally had success with pyinstaller: https://www.pyinstaller.org/ Pyinstaller can create executable files for Windows, OSX and Linux. Both the two approaches above significantly increase the size of your program as distributed to your users. You might have 3kB of code in a .py file that becomes 30MB as an .exe. > Is there some other way to get it working in either a browser... This suggests another way to provide access to your program to end users that involves minimal installation for them: make your program into a website. Then you can install Python on your server and your users just need to click a link. This obviously requires more resource on your part since you need to run (or hire) a server as well as writing a bit of code to adapt your program into a website. > ...or an Android/IOS app.... Normal Python GUI libraries don't work on these operating systems but Kivy does. You would need to switch to something like that instead of tkinter: https://kivy.org/#home Then you can package your code up as an app and put it on the app stores. Of course if you make a simple website then that would also work on smartphones as well as computers. Each of the different things above requires different amounts of work from you and from your users and places different constraints on your code. I would start by thinking about who should install your code and on what devices. The answer to that question will guide what you should do. For example, if this is for your students to show their friends/family then I would guess that smartphone apps are probably the main target, in which case look at kivy. -- Oscar From matthew.polack at htlc.vic.edu.au Thu Aug 23 00:47:49 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Thu, 23 Aug 2018 14:47:49 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: Hi Alan, I'm working my way through some of the tips you provided and tried to use the code given....but am getting an error at Line 75 in my code re: not enough arguments for format string _ return self.func(*args) File "Timespicture.py", line 75, in checkanswer Your current score is: %f""" % answer,score TypeError: not enough arguments for format string The instructions you game me were: > > Is there a way to simply combine all these commands with one txt.insert and > using commas? Not with commas but you can use line breaks inside a triple quoted string and just do a single insert. In fact one of the improvements I'd suggest for your code is to use string formatting to insert the values into your strings before inserting them. eg: fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" % answer,score txt.insert(1.0, fail_str, "center") Can you see what is going wrong? My code in that section has this: def checkanswer(): txt.delete(0.0, 'end') # as each variable changes outside of function...we need to make these global. global score global mistakes global total # checks for what is written in answerbox using the 'get' feature...makes it an integer. response = int(answerbox.get()) wordScore = "Your score is now " if response == answer: score += 1 total += 1 result = "Great Job! " root.update() viewSC() viewPercent() viewTotal() else : total += 1 result = "Sorry...you made a mistake. \n " # the \n above adds a line break. mistakes += 1 viewMistakes() viewTotal() viewPercent() fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" % answer,score txt.insert(1.0, fail_str, "center") Full code of whole program below.... Thanks! - Matt from tkinter import * import random # GLOBAL VARIABLES # Created with a starting value. answer = 0 score = 0 wrong = 0 mistakes = 0 total = 0 def makeproblem(): # access global answer...this is only required IF you need to update the variable within the function. # this happens below when answer is changed to number1 * number2 global answer # erases all text in current text box. txt.delete(0.0, 'end') sentence = "Here is your problem " # example of generating a random number. number1 = random.randint(2,12) number2 = random.randint(2,12) answer = number1 * number2 # creates a justification command called centre. (Not too sure why this is needed here...but not on the answer box elsewhere!) center = txt.tag_config("center", justify="center") txt.insert(0.0, sentence, "center") txt.insert(2.2, number1, "center") txt.insert(3.3, " x ", "center") txt.insert(4.4, number2, "center") def checkanswer(): txt.delete(0.0, 'end') # as each variable changes outside of function...we need to make these global. global score global mistakes global total # checks for what is written in answerbox using the 'get' feature...makes it an integer. response = int(answerbox.get()) wordScore = "Your score is now " if response == answer: score += 1 total += 1 result = "Great Job! " root.update() viewSC() viewPercent() viewTotal() else : total += 1 result = "Sorry...you made a mistake. \n " # the \n above adds a line break. mistakes += 1 viewMistakes() viewTotal() viewPercent() fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" % answer,score txt.insert(1.0, fail_str, "center") ''' center = txt.tag_config("center", justify="center") txt.insert(0.0, result, "center") txt.insert(3.0, wordScore, "center") txt.insert(8.1, score, "center") # txt.insert(1,1, "Score is") #txt.insert(3,3, score) ''' ''' All of the above could be replaced with a single format string and a single insert. display = """ Here is your problem: %d x %d """ % (number1, number2) txt.insert(1.0,display, "center") ''' def about(): txt.delete(0.0, 'end') instructions = "Here is how you play the game. Press generate problem..and then enter your answer. Your score will be displayed below." txt.insert(0.0,instructions) root = Tk() root.geometry("640x600+0+0") root.title("Times Tables Game") photo = PhotoImage(file="pool.gif") label = Label(image=photo) label.image = photo # keep a reference! label.grid(row=0, columnspan=20) # MENU SECTION # These are included as an example menu structure...in many cases they don't do much...but do feature instructions and a quit feature. # create a toplevel menu menubar = Menu(root) # Just an example of printing hello to console for use in a menu item. def hello(): print ("hello!") # display the menu root.config(menu=menubar) # create a pulldown menu, and adds it to the menu bar filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label="Open", command=makeproblem) filemenu.add_command(label="Save", command=makeproblem) filemenu.add_separator() filemenu.add_command(label="Exit", command=root.quit) menubar.add_cascade(label="File", menu=filemenu) # create more pulldown menus editmenu = Menu(menubar, tearoff=0) editmenu.add_command(label="Cut", command=checkanswer) editmenu.add_command(label="Copy", command=checkanswer) editmenu.add_command(label="Paste", command=checkanswer) menubar.add_cascade(label="Edit", menu=editmenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label="About", command=about) menubar.add_command(label="Hello", command=hello) menubar.add_cascade(label="Help", menu=helpmenu) menubar.add_command(label="Quit", command=root.quit) # Plain text labels at top of window. timeslabel = Label(root, text="Times Tables Practice", fg="white", bg="blue", font=("arial", 36, "bold")) timeslabel.grid(columnspan=12, sticky='ew') instruction = Label(root, text="Please click on the button to generate a problem", fg="blue", bg="white", font=("arial", 16, "bold")) instruction.grid(row=2, columnspan=20) # Makes an entry box with the variable of 'answerbox' answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify ="center") answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) # Makes a button that generate the Times Tables problem btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", command=makeproblem) btn.grid(row=11, columnspan=2, sticky=EW) # Makes a button that checks the answer btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", command=checkanswer) btn.grid(row=13, columnspan=2, sticky=EW) #TEXT BOX AREA #This important command creates the text box called 'txt'. This is used for all the text output. txt = Text(root, width=35, height=3, wrap=WORD, font=("arial", 20, "bold")) txt.grid(row=12, columnspan=2, sticky=EW ) #Adds a blankline below answer box...but leaves top alignment alone. You could use PAD...but that command does both sides. There may be another way to achieve this. blankline3 = Label(root, text = "", bg = "white") blankline3.grid(row=17, columnspan=2, sticky='ew') # SCORING LABELS AND RESULTS SECTION # Places the labels and the results beside each other in column 0 and column 1. # Note: Each 'View' label grabs the starting score from the declarations at the top. eg. score = 0 scorelab = Label(root, text="Score", bg="green", fg="white", font=("arial", 20, "bold")) scorelab.grid(row=18, column=0, sticky=E) scoreViewLab = Label(root, text=score, fg="black", bg="grey", font=("arial", 20, "bold")) scoreViewLab.grid(row=18, column=1, sticky=W) totalLab = Label(root, text="Out of", bg="purple", fg="white", font=("arial", 20, "bold")) totalLab.grid(row=19, column=0, sticky=E) totalViewLab = Label(root, text=total, fg="black", bg="grey", font=("arial", 20, "bold")) totalViewLab.grid(row=19, column=1, sticky=W) mistakeslab = Label(root, text="Mistakes", bg="red", fg="white", font=("arial", 20, "bold")) mistakeslab.grid(row=20, column=0, sticky=E) mistakesViewLab = Label(root, text=mistakes, fg="black", bg="grey", font=("arial", 20, "bold")) mistakesViewLab.grid(row=20, column=1, sticky=W) percentlab = Label(root, text="Percentage", bg="aqua", fg="white", font=("arial", 20, "bold")) percentlab.grid(row=21, column=0, sticky=E) percentViewLab = Label(root, text=0, fg="black", bg="grey", font=("arial", 20, "bold")) percentViewLab.grid(row=21, column=1, sticky=W) #SCORE UPDATE SECTION. # Each of these functions allows the 4 scoring labels to be updated as answers are deemed correct or incorrect with the if/else statement. # The viewPercent function includes the calculation to update the percentView label...shows an example of a calculation within a label. def viewSC(): scoreViewLab["text"] = score def viewTotal(): totalViewLab["text"] = total def viewMistakes(): mistakesViewLab["text"] = mistakes def viewPercent(): percentViewLab["text"] = score/total*100 ''' >>> s = "Here is a string with a rounded float: %.2f" % 42.3456789 >>> s 'Here is a string with a rounded float: 42.35' ''' # This keeps the program running. root.mainloop() Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Fri, Aug 17, 2018 at 8:18 PM, Alan Gauld via Tutor wrote: > On 17/08/18 03:19, Matthew Polack wrote: > > > def viewPercent(): > > percentCalc = score/total*100 > > rounded = round(percentCalc, 2) > > percentViewLab["text"] = rounded > > Since you only want the rounded value for display > this is usually achieved using string formatting: > > >>> s = "Here is a string with a rounded float: %.2f" % 42.3456789 > >>> s > 'Here is a string with a rounded float: 42.35' > > That doesn't change the value of the variable but changes how > it is displayed. There are lots of other options in format > strings to control justification, padding etc. You should > definitely explore their capabilities. Just because you > are using a GUI rather than a console doesn't mean the > string methods are any less useful. > > > from tkinter import * > > import random > > > > # GLOBAL VARIABLES > > # Created with a starting value. > > answer = 0 > > score = 0 > > wrong = 0 > > mistakes = 0 > > total = 0 > > > > def makeproblem(): > > global answer > > > > txt.delete(0.0, 'end') > > sentence = "Here is your problem " > > number1 = random.randint(2,12) > > number2 = random.randint(2,12) > > answer = number1 * number2 > > > > center = txt.tag_config("center", justify="center") > > > > txt.insert(0.0, sentence, "center") > > txt.insert(2.2, number1, "center") > > txt.insert(3.3, " x ", "center") > > txt.insert(4.4, number2, "center") > > All of the above could be replaced with a single format string > and a single insert. > > display = """ > Here is your problem: > > %d x %d > """ % (number1, number2) > > txt.insert(1.0,display, "center") > > > def checkanswer(): > > txt.delete(0.0, 'end') > > > > global score > > global mistakes > > global total > > Its conventional (although not necessary) to put all > globals at the very top of the function. > > > response = int(answerbox.get()) > > wordScore = "Your score is now " > > if response == answer: > > score += 1 > > total += 1 > > result = "Great Job! " > > root.update() > > viewSC() > > viewPercent() > > viewTotal() > > else : > > total += 1 > > result = "Sorry...you made a mistake. \n " > > # the \n above adds a line break. > > mistakes += 1 > > viewMistakes() > > viewTotal() > > viewPercent() > > Notice you display Total and Percent in both block > but do it in an inconsistent order. > If you took both of this display calls outside > the if/else you only need to call them once and > they will be in the same sequence for all cases. > > > center = txt.tag_config("center", justify="center") > > txt.insert(0.0, result, "center") > > txt.insert(3.0, wordScore, "center") > > txt.insert(8.1, score, "center") > > # txt.insert(1,1, "Score is") > > #txt.insert(3,3, score) > > Again this could all be replaced with string > formatting and a single insert() > > > def about(): > > txt.delete(0.0, 'end') > > > > instructions = "Here is how you play the game. Press generate > > problem..and then enter your answer. Your score will be displayed below." > > If you use triple quoted strings you can have > more text and lay it out using line breaks etc. > > > txt.insert(0.0,instructions) > > > > root = Tk() > > root.geometry("640x700+0+0") > > root.title("Times Tables Game") > > > > # MENU SECTION > > # These are included as an example menu structure...in many cases they > > don't do much...but do feature instructions and a quit feature. > > > > # create a toplevel menu > > menubar = Menu(root) > > > > # Just an example of printing hello to console for use in a menu item. > > def hello(): > > print ("hello!") > > > > # display the menu > > root.config(menu=menubar) > > > > # create a pulldown menu, and adds it to the menu bar > > filemenu = Menu(menubar, tearoff=0) > > filemenu.add_command(label="Open", command=makeproblem) > > filemenu.add_command(label="Save", command=makeproblem) > > filemenu.add_separator() > > filemenu.add_command(label="Exit", command=root.quit) > > > > menubar.add_cascade(label="File", menu=filemenu) > > > > # create more pulldown menus > > editmenu = Menu(menubar, tearoff=0) > > editmenu.add_command(label="Cut", command=checkanswer) > > editmenu.add_command(label="Copy", command=checkanswer) > > editmenu.add_command(label="Paste", command=checkanswer) > > menubar.add_cascade(label="Edit", menu=editmenu) > > > > helpmenu = Menu(menubar, tearoff=0) > > helpmenu.add_command(label="About", command=about) > > menubar.add_command(label="Hello", command=hello) > > menubar.add_cascade(label="Help", menu=helpmenu) > > menubar.add_command(label="Quit", command=root.quit) > > A bit odd adding a command after you add the cascade. > Normally we do the cascade as the last item. > > > # Plain text labels at top of window. > > timeslabel = Label(root, text="Times Tables Practice", fg="white", > > bg="blue", font=("arial", 36, "bold")) > > timeslabel.grid(columnspan=12, sticky='ew') > > instruction = Label(root, text="Please click on the button to generate a > > problem", fg="blue", bg="white", font=("arial", 16, "bold")) > > instruction.grid(row=2, columnspan=20) > > > > # Makes an entry box with the variable of 'answerbox' > > answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify > > ="center") > > answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) > > > > # Makes a button that generate the Times Tables problem > > btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", > > command=makeproblem) > > btn.grid(row=11, columnspan=2, sticky=EW) > > > > # Makes a button that checks the answer > > btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", > > command=checkanswer) > > btn.grid(row=13, columnspan=2, sticky=EW) > > > > #TEXT BOX AREA > > #This important command creates the text box called 'txt'. This is used > for > > all the text output. > > txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 20, > "bold")) > > txt.grid(row=12, columnspan=2, sticky=EW ) > > An interesting future option might be to eliminate this > text box and put it in a dialog (along with the result labels) > that would open to display the results in a separate window... > Consider it homework :-) > > > #Adds a blankline below answer box...but leaves top alignment alone. You > > could use PAD...but that command does both sides. There may be another > way > > to achieve this. > > You can do it in various ways including putting a label in a > frame and then anchoring the label to the bottom of the > frame... But an empty label will suffice here. Only GUI > purists would object. The easiest way is probably just to > insert a '\n' newline character at the start of the label > text. > > > blankline3 = Label(root, text = "", bg = "white") > > blankline3.grid(row=17, sticky='ew') > > > > # SCORING LABELS AND RESULTS SECTION > > # Places the labels and the results beside each other in column 0 and > > column 1. > > # Note: Each 'View' label grabs the starting score from the declarations > at > > the top. eg. score = 0 > > scorelab = Label(root, text="Score", bg="green", fg="white", > font=("arial", > > 20, "bold")) > > scorelab.grid(row=18, column=0, sticky=E) > > > > scoreViewLab = Label(root, text=score, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > scoreViewLab.grid(row=18, column=1, sticky=W) > > > > totalLab = Label(root, text="Out of", bg="purple", fg="white", > > font=("arial", 20, "bold")) > > totalLab.grid(row=19, column=0, sticky=E) > > > > totalViewLab = Label(root, text=total, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > totalViewLab.grid(row=19, column=1, sticky=W) > > > > mistakeslab = Label(root, text="Mistakes", bg="red", fg="white", > > font=("arial", 20, "bold")) > > mistakeslab.grid(row=20, column=0, sticky=E) > > > > mistakesViewLab = Label(root, text=mistakes, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > mistakesViewLab.grid(row=20, column=1, sticky=W) > > > > percentlab = Label(root, text="Percentage", bg="aqua", fg="white", > > font=("arial", 20, "bold")) > > percentlab.grid(row=21, column=0, sticky=E) > > > > > > percentViewLab = Label(root, text=0, fg="black", bg="grey", > font=("arial", > > 20, "bold")) > > percentViewLab.grid(row=21, column=1, sticky=W) > > > > > > #SCORE UPDATE SECTION. > > def viewSC(): > > scoreViewLab["text"] = score > > > > def viewTotal(): > > totalViewLab["text"] = total > > > > def viewMistakes(): > > mistakesViewLab["text"] = mistakes > > > > def viewPercent(): > > percentViewLab["text"] = rounded > > You could replace all of these with a > single function: > > def update_label(label,text): > label['text'] = text > > And supply change the calls from, for example: > > viewTotal() > > to > > update_label(totalViewLab, total) > > And you then need a function to calculate > the percent value: > > def percent_string(score, total): > return ".2f" % (score/total *100) > > > And you can now eliminate the percent global > variable and call update_label with: > > update_label(percentViewLab, percent_string(score, total)) > > > ##### Additional teachers notes #### > > As a general comment while you can use globals for > everything it considered bad practice. You should > strive to minimise use of global variables (google > global variables for lots of discussion about why). > Its generally considered better to make your functions > as independent as possible so that they take in values > via parameters and return a single value (occasionally > a tuple). As an example: > > # global var > value = 42 > > # define a function > def double(val): > return val * 2 > > # Now call it > value = double(value) > > So here we have not had to use the global keyword > but our function reads the global variable as input > and returns a new value which we assign to it. > > This relies on another good practice for functions > namely to keep them small and only do a single task. > If you find a single function updating lots of > global variables that often indicates that you > should have more than one function. > > In particular we try to separate display from > calculation. So in your case the check answer > function should really only check the answer > and set a success or failure flag. > You can then have a display result function > that checks the flag and updates all the > labels and text. > > Normally, I wouldn't highlight these issue to a > beginner but since you are also a teacher I felt > that you should be aware. They cross the boundary > from pure coding to software design. Your code as > it stands is acceptable for a beginner but in a > year you will probably look at it and cringe > slightly... But that is true with any new > coding venture. :-) > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From matthew.polack at htlc.vic.edu.au Thu Aug 23 01:10:05 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Thu, 23 Aug 2018 15:10:05 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: Hi Alan, I'm also trying to solve the rounding issue...but can't work out the syntax using the example provided...have tried this but I get an error... _tkinter.TclError: unknown option "-text %.2f" .I'm sure it is a simple syntax issue...but I don't know what it is. def viewPercent(): percentCalc = score/total*100 percentViewLab["text %.2f"] % percentCalc ''' # This was my working version pre the version suggest above. percentCalc = score/total*100 rounded = round(percentCalc, 2) percentViewLab["text"] = rounded ''' ''' Instructions given: >>> s = "Here is a string with a rounded float: %.2f" % 42.3456789 >>> s 'Here is a string with a rounded float: 42.35' ''' Thanks for any clues. - Matt Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Fri, Aug 17, 2018 at 8:18 PM, Alan Gauld via Tutor wrote: > On 17/08/18 03:19, Matthew Polack wrote: > > > def viewPercent(): > > percentCalc = score/total*100 > > rounded = round(percentCalc, 2) > > percentViewLab["text"] = rounded > > Since you only want the rounded value for display > this is usually achieved using string formatting: > > >>> s = "Here is a string with a rounded float: %.2f" % 42.3456789 > >>> s > 'Here is a string with a rounded float: 42.35' > > That doesn't change the value of the variable but changes how > it is displayed. There are lots of other options in format > strings to control justification, padding etc. You should > definitely explore their capabilities. Just because you > are using a GUI rather than a console doesn't mean the > string methods are any less useful. > > > from tkinter import * > > import random > > > > # GLOBAL VARIABLES > > # Created with a starting value. > > answer = 0 > > score = 0 > > wrong = 0 > > mistakes = 0 > > total = 0 > > > > def makeproblem(): > > global answer > > > > txt.delete(0.0, 'end') > > sentence = "Here is your problem " > > number1 = random.randint(2,12) > > number2 = random.randint(2,12) > > answer = number1 * number2 > > > > center = txt.tag_config("center", justify="center") > > > > txt.insert(0.0, sentence, "center") > > txt.insert(2.2, number1, "center") > > txt.insert(3.3, " x ", "center") > > txt.insert(4.4, number2, "center") > > All of the above could be replaced with a single format string > and a single insert. > > display = """ > Here is your problem: > > %d x %d > """ % (number1, number2) > > txt.insert(1.0,display, "center") > > > def checkanswer(): > > txt.delete(0.0, 'end') > > > > global score > > global mistakes > > global total > > Its conventional (although not necessary) to put all > globals at the very top of the function. > > > response = int(answerbox.get()) > > wordScore = "Your score is now " > > if response == answer: > > score += 1 > > total += 1 > > result = "Great Job! " > > root.update() > > viewSC() > > viewPercent() > > viewTotal() > > else : > > total += 1 > > result = "Sorry...you made a mistake. \n " > > # the \n above adds a line break. > > mistakes += 1 > > viewMistakes() > > viewTotal() > > viewPercent() > > Notice you display Total and Percent in both block > but do it in an inconsistent order. > If you took both of this display calls outside > the if/else you only need to call them once and > they will be in the same sequence for all cases. > > > center = txt.tag_config("center", justify="center") > > txt.insert(0.0, result, "center") > > txt.insert(3.0, wordScore, "center") > > txt.insert(8.1, score, "center") > > # txt.insert(1,1, "Score is") > > #txt.insert(3,3, score) > > Again this could all be replaced with string > formatting and a single insert() > > > def about(): > > txt.delete(0.0, 'end') > > > > instructions = "Here is how you play the game. Press generate > > problem..and then enter your answer. Your score will be displayed below." > > If you use triple quoted strings you can have > more text and lay it out using line breaks etc. > > > txt.insert(0.0,instructions) > > > > root = Tk() > > root.geometry("640x700+0+0") > > root.title("Times Tables Game") > > > > # MENU SECTION > > # These are included as an example menu structure...in many cases they > > don't do much...but do feature instructions and a quit feature. > > > > # create a toplevel menu > > menubar = Menu(root) > > > > # Just an example of printing hello to console for use in a menu item. > > def hello(): > > print ("hello!") > > > > # display the menu > > root.config(menu=menubar) > > > > # create a pulldown menu, and adds it to the menu bar > > filemenu = Menu(menubar, tearoff=0) > > filemenu.add_command(label="Open", command=makeproblem) > > filemenu.add_command(label="Save", command=makeproblem) > > filemenu.add_separator() > > filemenu.add_command(label="Exit", command=root.quit) > > > > menubar.add_cascade(label="File", menu=filemenu) > > > > # create more pulldown menus > > editmenu = Menu(menubar, tearoff=0) > > editmenu.add_command(label="Cut", command=checkanswer) > > editmenu.add_command(label="Copy", command=checkanswer) > > editmenu.add_command(label="Paste", command=checkanswer) > > menubar.add_cascade(label="Edit", menu=editmenu) > > > > helpmenu = Menu(menubar, tearoff=0) > > helpmenu.add_command(label="About", command=about) > > menubar.add_command(label="Hello", command=hello) > > menubar.add_cascade(label="Help", menu=helpmenu) > > menubar.add_command(label="Quit", command=root.quit) > > A bit odd adding a command after you add the cascade. > Normally we do the cascade as the last item. > > > # Plain text labels at top of window. > > timeslabel = Label(root, text="Times Tables Practice", fg="white", > > bg="blue", font=("arial", 36, "bold")) > > timeslabel.grid(columnspan=12, sticky='ew') > > instruction = Label(root, text="Please click on the button to generate a > > problem", fg="blue", bg="white", font=("arial", 16, "bold")) > > instruction.grid(row=2, columnspan=20) > > > > # Makes an entry box with the variable of 'answerbox' > > answerbox = Entry(root, bg="grey", font=("arial", 24, "bold"), justify > > ="center") > > answerbox.grid(row=15, columnspan=2, padx=0, pady=0, sticky=EW) > > > > # Makes a button that generate the Times Tables problem > > btn = Button(root, text="GENERATE PROBLEM", bg="blue", fg="white", > > command=makeproblem) > > btn.grid(row=11, columnspan=2, sticky=EW) > > > > # Makes a button that checks the answer > > btn = Button(root, text="CHECK ANSWER", bg="darkblue", fg="white", > > command=checkanswer) > > btn.grid(row=13, columnspan=2, sticky=EW) > > > > #TEXT BOX AREA > > #This important command creates the text box called 'txt'. This is used > for > > all the text output. > > txt = Text(root, width=35, height=8, wrap=WORD, font=("arial", 20, > "bold")) > > txt.grid(row=12, columnspan=2, sticky=EW ) > > An interesting future option might be to eliminate this > text box and put it in a dialog (along with the result labels) > that would open to display the results in a separate window... > Consider it homework :-) > > > #Adds a blankline below answer box...but leaves top alignment alone. You > > could use PAD...but that command does both sides. There may be another > way > > to achieve this. > > You can do it in various ways including putting a label in a > frame and then anchoring the label to the bottom of the > frame... But an empty label will suffice here. Only GUI > purists would object. The easiest way is probably just to > insert a '\n' newline character at the start of the label > text. > > > blankline3 = Label(root, text = "", bg = "white") > > blankline3.grid(row=17, sticky='ew') > > > > # SCORING LABELS AND RESULTS SECTION > > # Places the labels and the results beside each other in column 0 and > > column 1. > > # Note: Each 'View' label grabs the starting score from the declarations > at > > the top. eg. score = 0 > > scorelab = Label(root, text="Score", bg="green", fg="white", > font=("arial", > > 20, "bold")) > > scorelab.grid(row=18, column=0, sticky=E) > > > > scoreViewLab = Label(root, text=score, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > scoreViewLab.grid(row=18, column=1, sticky=W) > > > > totalLab = Label(root, text="Out of", bg="purple", fg="white", > > font=("arial", 20, "bold")) > > totalLab.grid(row=19, column=0, sticky=E) > > > > totalViewLab = Label(root, text=total, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > totalViewLab.grid(row=19, column=1, sticky=W) > > > > mistakeslab = Label(root, text="Mistakes", bg="red", fg="white", > > font=("arial", 20, "bold")) > > mistakeslab.grid(row=20, column=0, sticky=E) > > > > mistakesViewLab = Label(root, text=mistakes, fg="black", bg="grey", > > font=("arial", 20, "bold")) > > mistakesViewLab.grid(row=20, column=1, sticky=W) > > > > percentlab = Label(root, text="Percentage", bg="aqua", fg="white", > > font=("arial", 20, "bold")) > > percentlab.grid(row=21, column=0, sticky=E) > > > > > > percentViewLab = Label(root, text=0, fg="black", bg="grey", > font=("arial", > > 20, "bold")) > > percentViewLab.grid(row=21, column=1, sticky=W) > > > > > > #SCORE UPDATE SECTION. > > def viewSC(): > > scoreViewLab["text"] = score > > > > def viewTotal(): > > totalViewLab["text"] = total > > > > def viewMistakes(): > > mistakesViewLab["text"] = mistakes > > > > def viewPercent(): > > percentViewLab["text"] = rounded > > You could replace all of these with a > single function: > > def update_label(label,text): > label['text'] = text > > And supply change the calls from, for example: > > viewTotal() > > to > > update_label(totalViewLab, total) > > And you then need a function to calculate > the percent value: > > def percent_string(score, total): > return ".2f" % (score/total *100) > > > And you can now eliminate the percent global > variable and call update_label with: > > update_label(percentViewLab, percent_string(score, total)) > > > ##### Additional teachers notes #### > > As a general comment while you can use globals for > everything it considered bad practice. You should > strive to minimise use of global variables (google > global variables for lots of discussion about why). > Its generally considered better to make your functions > as independent as possible so that they take in values > via parameters and return a single value (occasionally > a tuple). As an example: > > # global var > value = 42 > > # define a function > def double(val): > return val * 2 > > # Now call it > value = double(value) > > So here we have not had to use the global keyword > but our function reads the global variable as input > and returns a new value which we assign to it. > > This relies on another good practice for functions > namely to keep them small and only do a single task. > If you find a single function updating lots of > global variables that often indicates that you > should have more than one function. > > In particular we try to separate display from > calculation. So in your case the check answer > function should really only check the answer > and set a success or failure flag. > You can then have a display result function > that checks the flag and updates all the > labels and text. > > Normally, I wouldn't highlight these issue to a > beginner but since you are also a teacher I felt > that you should be aware. They cross the boundary > from pure coding to software design. Your code as > it stands is acceptable for a beginner but in a > year you will probably look at it and cringe > slightly... But that is true with any new > coding venture. :-) > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From alan.gauld at yahoo.co.uk Thu Aug 23 08:05:36 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 23 Aug 2018 13:05:36 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 23/08/18 05:47, Matthew Polack wrote: > Hi Alan, > > I'm working my way through some of the tips you provided and tried to use > the code given....but am getting an error at Line 75 in my code re: not > enough arguments for format string > > _ > return self.func(*args) > File "Timespicture.py", line 75, in checkanswer > Your current score is: %f""" % answer,score > TypeError: not enough arguments for format string Lets go back to basics with Python assignment. In your example you have a format string as: fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" And you try to insert 2 values, answer and score. Unfortunately Python sees it like this: fail_string = someData, moreData Where someData looks like fmtString % answer and moreData looks like score. The solution is to use parentheses to create an explicit tuple to group both of your data values together: fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" % (answer,score) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Thu Aug 23 08:19:10 2018 From: __peter__ at web.de (Peter Otten) Date: Thu, 23 Aug 2018 14:19:10 +0200 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! References: Message-ID: Matthew Polack wrote: > I'm working my way through some of the tips you provided and tried to use > the code given....but am getting an error at Line 75 in my code re: not > enough arguments for format string > > _ > return self.func(*args) > File "Timespicture.py", line 75, in checkanswer > Your current score is: %f""" % answer,score > TypeError: not enough arguments for format string > fail_str = """ > Sorry, you got it wrong, > the correct answer was %d > Your current score is: %f""" % answer,score Python reads some_str % arg1, arg2 as (some_str % arg1), arg2 To make the above work you have to use parens: fail_str = """ Sorry, you got it wrong, the correct answer was %d Your current score is: %f""" % (answer, score) Another option is to use f-strings to sidestep the issue: fail_str = f""" Sorry, you got it wrong, the correct answer was {answer} Your current score is: {score}""" From sjeik_appie at hotmail.com Thu Aug 23 08:32:49 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Thu, 23 Aug 2018 12:32:49 +0000 Subject: [Tutor] Building a Package In-Reply-To: <5856b8c4-65d5-41a1-8f42-3a200a29fff1@me.com> Message-ID: On 21 Aug 2018 15:10, Glenn Schultz via Tutor wrote: All, I have a project pthon(3.7) I have followed the python setup instructions. I get a dist folder with the correct files. Now, I would like to install locally from my local machine (note I am not using virtual enviroment as our firewall does not allow installation of packages when using VE). In my site packages directory I get the foo.dist-info but not foo folder. Using setuptools and following the packaging python project I had to # out over 70% of the example setup as they were all throwing warnings etc. and prohibiting the final build. Is there an alternative source to guide one through project packaging? Its now been two-days of struggle with no success. I would like to migrate some of my projects from R to Python. But, honestly, packaging a python project seems far more difficult than building an R package. I'm not trolling Python vs. R but my God, the level of frustration with python packaging is about to make me walk away. Either I am a complete moron or packaging python is a poorly documented nightmare. If anyone can point me to source for pyhton packaging that is better than the Packaging Python Projects website I would greatly appreciate the direction. ====>> check out https://pypi.org//PyScaffold/ or https://github.com/audreyr/cookiecutter From __peter__ at web.de Thu Aug 23 08:32:51 2018 From: __peter__ at web.de (Peter Otten) Date: Thu, 23 Aug 2018 14:32:51 +0200 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! References: Message-ID: Matthew Polack wrote: > I'm also trying to solve the rounding issue...but can't work out the > syntax using the example provided...have tried this but I get an error... > > _tkinter.TclError: unknown option "-text %.2f" > > .I'm sure it is a simple syntax issue...but I don't know what it is. > > def viewPercent(): > percentCalc = score/total*100 > percentViewLab["text %.2f"] % percentCalc I'm sure you can resolve that one yourself. You have obj[key] = float_value Now you want to format the float value as a string showing a decimal number. So all you need to change is the righthand side. If it helps write it in two lines: some_string = ... expression involving float_value ... obj[key] = some_string From alan.gauld at yahoo.co.uk Thu Aug 23 08:34:22 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 23 Aug 2018 13:34:22 +0100 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: On 23/08/18 06:10, Matthew Polack wrote: > I'm also trying to solve the rounding issue...but can't work out the syntax > using the example provided...have tried this but I get an error... > > def viewPercent(): > percentCalc = score/total*100 > percentViewLab["text %.2f"] % percentCalc OK, the problem here is mixing up your data with TKinter's (inherited from Tcl/Tk) mechanism for accessing widget attributes. percentViewLab["text %.2f"] This tells Tkinter to fetch an attribute of your widget called "text %.2f". Of course there is no such attribute, it is called just "text". percentViewLab["text %.2f"] % percentCalc This tries to insert the percentCalc value into the string returned by the widget. Again that's not what you want. You want to insert the data into a string which will then be assigned to the widget's text attribute. val = "%.2f" % percentCalc # eg. -> val = "0.76" Now insert val into your widget percentViewLab["text"] = val or equivalently: percentViewLab.config("text", val) You can of course combine all of that with percentViewLab["text"] = ".2f" % percentCalc Personally I tend to separate the creation of the string from the widget assignment because it makes it easier to debug by printing the string to the console. One final note. When using % to inject data into a format string you MUST put the percent immediately after the format string. No commas or parentheses allowed. The % formatting style is preferred by old school programmers (like me) who came from the world of C and its relatives because C uses a very similar style in its printf() family of functions. However, new programmers may find the format() method of a string more obvious. (I'm thinking about your students here) Using format your case would look like: val = "{:.2f}".format(percentCalc) And the previous example would be: fail_str = """ Sorry, you got it wrong, the correct answer was {:d} Your current score is: {:f}""".format(answer,score) It is quite similar except the placemarkers are {} and you call the format() method. The formatting characters inside the {} are different too - you need to read the docs... There are zillions of examples. You might find it more logical. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From glennmschultz at me.com Thu Aug 23 11:06:21 2018 From: glennmschultz at me.com (Glenn Schultz) Date: Thu, 23 Aug 2018 15:06:21 +0000 (GMT) Subject: [Tutor] build does not include all .py modules Message-ID: All, followed links and suggestions and I have resolved most issues. ?I continue to follow the python.org instructions as well. ?The package builds and creates all the requsite files. ?The challenge I am facing now is that the __init__.py does not include all the modules. ?Below is a screen shot of the structure and result after the build. The build and and lib files are fine as well. ?Everything is there with no errors or warning. ?When I run a test script I can import prepaymentmodeling but I get an error NameError name 'loandata' is not defined. ?My __ini__.py successfully imported all package dependencies but did not import all the files it looks like this. only traintest and loandata is remarked out. ?The balance do not even show up. ?I searched the python site and SO but I am at a loss since it all looks good per the python.org instructions and links you guys sent me the other day. ?Does anyone have an thoughts as to what is creating the problem? Soooo close it hurts, Glenn __ini__.py looks like this all package imports are okay ..... from .traintest import * #from loandata import * From matthew.polack at htlc.vic.edu.au Thu Aug 23 20:47:52 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Fri, 24 Aug 2018 10:47:52 +1000 Subject: [Tutor] Times Tables Program that constantly tells you that you are wrong! In-Reply-To: References: Message-ID: Thanks Alan and Peter for all your help with this. I got it all to work..thank you.. like learning a musical instrument...probably just need some time consolidating the current skill set...has been a lot to take in... but getting there steadily...and bit by bit it is starting to make sense.. I'll probably stick with the traditional %. method too for a while because that is now what I understand. thanks...will keep trying things..and then also reading through the various docs provided...+ your emails. Thank you. Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au On Thu, Aug 23, 2018 at 10:34 PM, Alan Gauld via Tutor wrote: > On 23/08/18 06:10, Matthew Polack wrote: > > > I'm also trying to solve the rounding issue...but can't work out the > syntax > > using the example provided...have tried this but I get an error... > > > > > def viewPercent(): > > percentCalc = score/total*100 > > percentViewLab["text %.2f"] % percentCalc > > OK, the problem here is mixing up your data with TKinter's > (inherited from Tcl/Tk) mechanism for accessing widget > attributes. > > percentViewLab["text %.2f"] > > This tells Tkinter to fetch an attribute of your widget > called "text %.2f". Of course there is no such attribute, > it is called just "text". > > percentViewLab["text %.2f"] % percentCalc > > This tries to insert the percentCalc value into the > string returned by the widget. > > Again that's not what you want. You want to insert > the data into a string which will then be assigned > to the widget's text attribute. > > val = "%.2f" % percentCalc # eg. -> val = "0.76" > > Now insert val into your widget > > percentViewLab["text"] = val > > or equivalently: > > percentViewLab.config("text", val) > > You can of course combine all of that with > > percentViewLab["text"] = ".2f" % percentCalc > > Personally I tend to separate the creation of the > string from the widget assignment because it makes > it easier to debug by printing the string to the > console. > > One final note. When using % to inject data into > a format string you MUST put the percent immediately > after the format string. No commas or parentheses > allowed. > > The % formatting style is preferred by old school > programmers (like me) who came from the world of C and > its relatives because C uses a very similar style in > its printf() family of functions. However, new programmers > may find the format() method of a string more obvious. > (I'm thinking about your students here) > > Using format your case would look like: > > val = "{:.2f}".format(percentCalc) > > And the previous example would be: > > fail_str = """ > Sorry, you got it wrong, > the correct answer was {:d} > Your current score is: {:f}""".format(answer,score) > > It is quite similar except the placemarkers are {} > and you call the format() method. The formatting > characters inside the {} are different too - you > need to read the docs... There are zillions of examples. > You might find it more logical. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From alan.gauld at yahoo.co.uk Fri Aug 24 05:02:13 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 24 Aug 2018 10:02:13 +0100 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: <9b9d6b2e-ade1-9ebf-39bb-388a110d748f@wichmann.us> Message-ID: CCing list, please always use Reply-All or Reply-List when responding to the tutor list so that everyone gets a chance to reply. On 24/08/18 00:35, Roger Lea Scherer wrote: > > Lots of code missing, but the line I'm interested in is this: > print("Your number? " + str(numerator) + "/" + str(denominator) + "? > is approximately? " + str(fractions[ranges[i][0]][0]) + "/" + > str(fractions[ranges[i][0]][1])) > I get this output: > Your number? 37/112? is approximately? 1/3 > > From this line: > print("Your number ",? numerator, "/",? denominator, " is > approximately ", fractions[ranges[i][0]][0], "/", > fractions[ranges[i][0]][1]) > I get this output: > Your number? 37 / 112? is approximately? 1 / 3 > > I'm being picky. I don't like the spaces between the 37 and 112 and 1 > and 3... > my question is: Is there another way other than these two to > print without all the str nonsense and not get the spaces Yes, use string formatting. It gives you much more control over the content of your string including field width, number of decimal places, justification, etc. For example in your case: print("Your number? %d/%d is approximately %d/%d" % (numerator, ???????????????????????????????????????????????????? denominator, ???????????????????????????????????????????????????? fractions[ranges[i][0]][0], ???????????????????????????????????????????????????? fractions[ranges[i][0]][1])) The stacked layout is of course optional, I just think it looks clearer. See the thread on TimesTable for more on formatting and look at the documentation : https://docs.python.org/3/library/stdtypes.html#old-string-formatting and https://docs.python.org/3/library/string.html#formatstrings Use whichever style you prefer. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Fri Aug 24 05:19:32 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 24 Aug 2018 10:19:32 +0100 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: <9b9d6b2e-ade1-9ebf-39bb-388a110d748f@wichmann.us> Message-ID: On 24/08/18 10:02, Alan Gauld via Tutor wrote: > CCing list, please always use Reply-All or Reply-List when responding > to the tutor list so that everyone gets a chance to reply. > > > On 24/08/18 00:35, Roger Lea Scherer wrote: >> >> Lots of code missing, but the line I'm interested in is this: >> print("Your number? " + str(numerator) + "/" + str(denominator) + "? >> is approximately? " + str(fractions[ranges[i][0]][0]) + "/" + >> str(fractions[ranges[i][0]][1])) >> I get this output: >> Your number? 37/112? is approximately? 1/3 >> > print("Your number? %d/%d is approximately %d/%d" % (numerator, > ???????????????????????????????????????????????????? denominator, > fractions[ranges[i][0]][0], > fractions[ranges[i][0]][1])) > > The stacked layout is of course optional, I just think it looks clearer. It would look clearer if the mail hadn't messed it up! :-) The two fractions() lines were intended to be under the numerator,denominator values not on the left side! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From sjeik_appie at hotmail.com Fri Aug 24 11:16:01 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Fri, 24 Aug 2018 15:16:01 +0000 Subject: [Tutor] need help generating table of contents Message-ID: Hello, I have Ghostscript files with a table of contents (toc)?and I would like to use this info to generate a human-readable toc. The problem is: I can't get the (nested) hierarchy right. import re toc = """\ [ /PageMode /UseOutlines ? /Page 1 ? /View [/XYZ null null 0] ? /DOCVIEW pdfmark [ /Title (Title page) ? /Page 1 ? /View [/XYZ null null 0] ? /OUT pdfmark [ /Title (Document information) ? /Page 2 ? /View [/XYZ null null 0] ? /OUT pdfmark [ /Title (Blah) ? /Page 3 ? /View [/XYZ null null 0] ? /OUT pdfmark [ /Title (Appendix) ? /Page 16 ? /Count 4 ? /View [/XYZ null null 0] ? /OUT pdfmark ??? [ /Title (Sub1) ????? /Page 17 ????? /Count 4 ????? /OUT pdfmark ??? [ /Title (Subsub1) ????? /Page 17 ????? /OUT pdfmark ??? [ /Title (Subsub2) ????? /Page 18 ????? /OUT pdfmark ??? [ /Title (Subsub3) ????? /Page 29 ????? /OUT pdfmark ??? [ /Title (Subsub4) ????? /Page 37 ????? /OUT pdfmark ??? [ /Title (Sub2) ????? /Page 40 ????? /OUT pdfmark ??? [ /Title (Sub3) ????? /Page 49 ????? /OUT pdfmark ??? [ /Title (Sub4) ????? /Page 56 ????? /OUT pdfmark """??? print('\r\n** Table of contents\r\n') pattern = '/Title \((.+?)\).+?/Page ([0-9]+)(?:\s+/Count ([0-9]+))?' indent = 0 start = True for title, page, count in re.findall(pattern, toc, re.DOTALL): ??? title = (indent * ' ') + title ??? count = int(count or 0) ??? print(title.ljust(79, ".") + page.zfill(2)) ??? if count: ??????? count -= 1 ??????? start = True ??? if count and start: ??????? indent += 2 ??????? start = False ??? if not count and not start: ??????? indent -= 2 ??????? start = True This generates the following TOC, with subsub2 to subsub4 dedented one level too much: ** Table of contents Title page.....................................................................01 Document information...........................................................02 Blah...........................................................................03 Appendix.......................................................................16 ? Sub1.........................................................................17 ??? Subsub1....................................................................17 ? Subsub2......................................................................18 ? Subsub3......................................................................29 ? Subsub4......................................................................37 ? Sub2.........................................................................40 ? Sub3.........................................................................49 ? Sub4.........................................................................56 What is the best approach to do this? Thanks in advance! Albert-Jan From mats at wichmann.us Fri Aug 24 11:14:11 2018 From: mats at wichmann.us (Mats Wichmann) Date: Fri, 24 Aug 2018 09:14:11 -0600 Subject: [Tutor] Accessing a tuple of a dictionary's value In-Reply-To: References: <9b9d6b2e-ade1-9ebf-39bb-388a110d748f@wichmann.us> Message-ID: <10648fa4-e202-c47e-06e0-0fb00e7643fe@wichmann.us> On 08/24/2018 03:02 AM, Alan Gauld via Tutor wrote: > CCing list, please always use Reply-All or Reply-List when responding > to the tutor list so that everyone gets a chance to reply. > > > On 24/08/18 00:35, Roger Lea Scherer wrote: >> >> Lots of code missing, but the line I'm interested in is this: >> print("Your number? " + str(numerator) + "/" + str(denominator) + "? >> is approximately? " + str(fractions[ranges[i][0]][0]) + "/" + >> str(fractions[ranges[i][0]][1])) >> I get this output: >> Your number? 37/112? is approximately? 1/3 >> >> From this line: >> print("Your number ",? numerator, "/",? denominator, " is >> approximately ", fractions[ranges[i][0]][0], "/", >> fractions[ranges[i][0]][1]) >> I get this output: >> Your number? 37 / 112? is approximately? 1 / 3 >> >> I'm being picky. I don't like the spaces between the 37 and 112 and 1 >> and 3... > >> my question is: Is there another way other than these two to >> print without all the str nonsense and not get the spaces > > Yes, use string formatting. In addition, let's understand what is happening above. print("Your number ", numerator, "/", denominator, " is approximately ", fractions[ranges[i][0]][0], "/", fractions[ranges[i][0]][1]) You are doing two things in this line 1. construct a string 2. print the string The constructed string is never assigned a name, so it is not saved after the print function is done with it (no more references), but that's what is happening. In constructing the string, there are about a zillion options, in this case it is "adding" smaller string pieces together. Try: s = "hello" + "world" print(s) no spaces :) the string class provides a "+" operator which is just concatenation. So when building up a new string this way, put spaces in if you want them, and don't put spaces in if you don't. If your intent it to nicely format a string for visual display on your terminal or to a file, then string concatenation is a more cumbersome route than tools which are designed for the purpose, but there are plenty of good uses for it as well. From __peter__ at web.de Fri Aug 24 11:55:21 2018 From: __peter__ at web.de (Peter Otten) Date: Fri, 24 Aug 2018 17:55:21 +0200 Subject: [Tutor] need help generating table of contents References: Message-ID: Albert-Jan Roskam wrote: > Hello, > > I have Ghostscript files with a table of contents (toc) and I would like to use this info to generate a human-readable toc. The problem is: I can't get the (nested) hierarchy right. > > import re > > toc = """\ > [ /PageMode /UseOutlines > /Page 1 > /View [/XYZ null null 0] > /DOCVIEW pdfmark > [ /Title (Title page) > /Page 1 > /View [/XYZ null null 0] > /OUT pdfmark > [ /Title (Document information) > /Page 2 > /View [/XYZ null null 0] > /OUT pdfmark > [ /Title (Blah) > /Page 3 > /View [/XYZ null null 0] > /OUT pdfmark > [ /Title (Appendix) > /Page 16 > /Count 4 > /View [/XYZ null null 0] > /OUT pdfmark > [ /Title (Sub1) > /Page 17 > /Count 4 > /OUT pdfmark > [ /Title (Subsub1) > /Page 17 > /OUT pdfmark > [ /Title (Subsub2) > /Page 18 > /OUT pdfmark > [ /Title (Subsub3) > /Page 29 > /OUT pdfmark > [ /Title (Subsub4) > /Page 37 > /OUT pdfmark > [ /Title (Sub2) > /Page 40 > /OUT pdfmark > [ /Title (Sub3) > /Page 49 > /OUT pdfmark > [ /Title (Sub4) > /Page 56 > /OUT pdfmark > """ > print('\r\n** Table of contents\r\n') > pattern = '/Title \((.+?)\).+?/Page ([0-9]+)(?:\s+/Count ([0-9]+))?' > indent = 0 > start = True > for title, page, count in re.findall(pattern, toc, re.DOTALL): > title = (indent * ' ') + title > count = int(count or 0) > print(title.ljust(79, ".") + page.zfill(2)) > if count: > count -= 1 > start = True > if count and start: > indent += 2 > start = False > if not count and not start: > indent -= 2 > start = True > > This generates the following TOC, with subsub2 to subsub4 dedented one level too much: > What is the best approach to do this? The best approach is probably to use some tool/library that understands postscript. However, your immediate problem is that when there is more than one level of indentation you only keep track of the "count" of the innermost level. You can either use a list of counts or use recursion and rely on the stack to remember the counts of the outer levels. The following reshuffle of your code seems to work: print('\r\n** Table of contents\r\n') pattern = '/Title \((.+?)\).+?/Page ([0-9]+)(?:\s+/Count ([0-9]+))?' def process(triples, limit=None, indent=0): for index, (title, page, count) in enumerate(triples, 1): title = indent * 4 * ' ' + title print(title.ljust(79, ".") + page.zfill(2)) if count: process(triples, limit=int(count), indent=indent+1) if limit is not None and limit == index: break process(iter(re.findall(pattern, toc, re.DOTALL))) From cs at cskk.id.au Sat Aug 25 18:40:58 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Sun, 26 Aug 2018 08:40:58 +1000 Subject: [Tutor] need help generating table of contents In-Reply-To: References: Message-ID: <20180825224058.GA82833@cskk.homeip.net> On 24Aug2018 17:55, Peter Otten <__peter__ at web.de> wrote: >Albert-Jan Roskam wrote: >> I have Ghostscript files with a table of contents (toc) and I would like >to use this info to generate a human-readable toc. The problem is: I can't >get the (nested) hierarchy right. >> >> import re >> >> toc = """\ >> [ /PageMode /UseOutlines >> /Page 1 >> /View [/XYZ null null 0] >> /DOCVIEW pdfmark >> [ /Title (Title page) >> /Page 1 >> /View [/XYZ null null 0] >> /OUT pdfmark >> [ /Title (Document information) >> /Page 2 >> /View [/XYZ null null 0] >> /OUT pdfmark [...] >> What is the best approach to do this? > >The best approach is probably to use some tool/library that understands >postscript. Just to this: I disagree. IIRC, there's no such thing as '/Title' etc in PostScript - these will all be PostScript functions defined by whatever made the document. So a generic tool won't have any way to extract semantics like titles from a document. The OP presumably has the specific output of a particular tool with this nice well structured postscript, so he needs to write his/her own special parser. Cheers, Cameron Simpson From robertvstepp at gmail.com Sun Aug 26 18:38:52 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 26 Aug 2018 17:38:52 -0500 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? Message-ID: Python 3.6.6, Linux Mint I feel that I may be missing something truly obvious. I am pondering the design of a solitaire scorekeeper program. It is just meant to be an electronic scorekeeper for hands of solitaire that I plan with a "real" deck of cards, instead of a computer game. I might want to play and track a variety of solitaire games. And I might want to play one game for a bit and then switch to another. One version of solitaire I might play has thirteen possible separately scored versions, depending on which of thirteen cards gets turned up in the beginning (2, 3, 4, ... , J, Q, K, A). So each hand played needs to be scored under its own card. I would need to be able to switch back and forth between all thirteen at need to enter a score for a hand. So no matter what solitaire game I am playing it seems that it would boil down to: class SolitaireGame(): def __init__(self, name): self.name = name Say I go with the aforementioned game with 13 separate scores to keep track of. The names of these games might be "Two_Mastery", "Three_Mastery", ... , "Ace_Mastery". In principle I want 13 objects with each one keeping track of each of the above games. Then I might want to switch to "Spider_Solitaire", keep track of its score, then go to something else, then back to Mastery, etc. How on earth am I to generate unique identifiers for each of these SolitaireGame objects in a rational way, not knowing in advance moment to moment what type of solitaire game I might be playing? I am *not* wanting to discard one object prior to creating a new one for a new game. I would like to have all such objects to peacefully coexist and be able to switch between them at will. Of course the intent is to persistently store these objects on disk upon program closure. TIA! -- boB From michaelrbms at gmail.com Sun Aug 26 13:42:32 2018 From: michaelrbms at gmail.com (Michael Munn) Date: Sun, 26 Aug 2018 13:42:32 -0400 Subject: [Tutor] =?utf-8?q?Hi_This_is_Michael_Munn_and_I=E2=80=99m_intere?= =?utf-8?q?sted_of_the_Python_programming_language=2E?= Message-ID: Hi All, This is Michael and I have a question about resources on starting to code python. I?m using Python 3.6 and I heard a friend of mine told me that He write his code using a word processer called Note pad plus some thing like that to code. Any idea where to get this word Processer? Please respond if you all get any chance. Best Regards Michael Munn PS This question might sounds Stupid to you all. I just want you all to know that I?m a beginner Pythonist. And I know Nothing about coding at all. I ask you not to laugh at me if I post question like this in the future. Thanks and have a nice day. Best REGARDS michael Munn From alan.gauld at yahoo.co.uk Sun Aug 26 19:09:10 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 27 Aug 2018 00:09:10 +0100 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: On 26/08/18 23:38, boB Stepp wrote: > class SolitaireGame(): > def __init__(self, name): > self.name = name > Say I go with the aforementioned game with 13 separate scores to keep > track of. The names of these games might be "Two_Mastery", > "Three_Mastery", ... , "Ace_Mastery". In principle I want 13 objects > with each one keeping track of each of the above games. Then I might > want to switch to "Spider_Solitaire", keep track of its score, then go > to something else, then back to Mastery, etc. How on earth am I to > generate unique identifiers for each of these SolitaireGame objects in > a rational way, not knowing in advance moment to moment what type of > solitaire game I might be playing? A dictionary of objects keyed by name? If using a GUI add the names to a drop down or listbox to ease later selection. Does that work for you? > between them at will. Of course the intent is to persistently store > these objects on disk upon program closure. Maybe JSON for that? Or even a shelve database? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Sun Aug 26 19:19:20 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 27 Aug 2018 00:19:20 +0100 Subject: [Tutor] =?utf-8?q?Hi_This_is_Michael_Munn_and_I=E2=80=99m_intere?= =?utf-8?q?sted_of_the_Python_programming_language=2E?= In-Reply-To: References: Message-ID: On 26/08/18 18:42, Michael Munn wrote: > I?m using Python 3.6 and I heard a friend of mine told me that He write his > code using a word processer called Note pad plus some thing like that to > code. I assume you are on Windows OS? In which case you probably mean Notepad++ (like in the C++ programming language) It's a well known programmer's editor for Windows. Note that it is not a Word Processor, it has no support for formatting text (fonts, justification etc) it is just a powerful text editor, which is what you need for programming. Most importantly it saves in plain text not in a binary or XML/HTML format. > Any idea where to get this word Processer? A web search for Notepad++ should find it. However Python comes with a useful programming environment called Idle which you can use instead. It is Python specific whereas Notepad++ caters for many languages but if you are starting out in Python Idle is a fair choice and its already installed! I don't use Windows for Python work but last time I looked it was called something like Python GUI in the Windows start menu. > PS This question might sounds Stupid to you all. Not at all, choice of programming toolset is a very personal opinion and you will likely get several suggestions. > I ask you not to laugh at me if I post question like this in the future. We won't laugh, its why we are here. When posting questions always try to be as specific as possible, post any code you have and the full text of any error messages. Also post in plain text if possibly, email servers tends to mess up code otherwise. A reminder of your OS and Python version is also useful. Have fun, -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From mats at wichmann.us Sun Aug 26 19:48:39 2018 From: mats at wichmann.us (Mats Wichmann) Date: Sun, 26 Aug 2018 17:48:39 -0600 Subject: [Tutor] =?utf-8?q?Hi_This_is_Michael_Munn_and_I=E2=80=99m_intere?= =?utf-8?q?sted_of_the_Python_programming_language=2E?= In-Reply-To: References: Message-ID: see also https://wiki.python.org/moin/PythonEditors On August 26, 2018 5:19:20 PM MDT, Alan Gauld via Tutor wrote: >On 26/08/18 18:42, Michael Munn wrote: > >> I?m using Python 3.6 and I heard a friend of mine told me that He >write his >> code using a word processer called Note pad plus some thing like that >to >> code. > >I assume you are on Windows OS? >In which case you probably mean Notepad++ (like >in the C++ programming language) > >It's a well known programmer's editor for Windows. > >Note that it is not a Word Processor, it has >no support for formatting text (fonts, justification >etc) it is just a powerful text editor, which is >what you need for programming. Most importantly >it saves in plain text not in a binary or XML/HTML >format. > >> Any idea where to get this word Processer? > >A web search for Notepad++ should find it. >However Python comes with a useful programming >environment called Idle which you can use instead. >It is Python specific whereas Notepad++ caters >for many languages but if you are starting out >in Python Idle is a fair choice and its already >installed! > >I don't use Windows for Python work but last >time I looked it was called something like >Python GUI in the Windows start menu. > >> PS This question might sounds Stupid to you all. > >Not at all, choice of programming toolset is >a very personal opinion and you will likely >get several suggestions. > >> I ask you not to laugh at me if I post question like this in the >future. >We won't laugh, its why we are here. > >When posting questions always try to be as specific >as possible, post any code you have and the full >text of any error messages. Also post in plain text >if possibly, email servers tends to mess up code >otherwise. > >A reminder of your OS and Python version is also useful. > >Have fun, > >-- >Alan G >Author of the Learn to Program web site >http://www.alan-g.me.uk/ >http://www.amazon.com/author/alan_gauld >Follow my photo-blog on Flickr at: >http://www.flickr.com/photos/alangauldphotos > > >_______________________________________________ >Tutor maillist - Tutor at python.org >To unsubscribe or change subscription options: >https://mail.python.org/mailman/listinfo/tutor -- Sent from my Android device with K-9 Mail. Please excuse my brevity. From steve at pearwood.info Sun Aug 26 20:47:25 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 27 Aug 2018 10:47:25 +1000 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: <20180827004725.GB24160@ando.pearwood.info> On Sun, Aug 26, 2018 at 05:38:52PM -0500, boB Stepp wrote: > I feel that I may be missing something truly obvious. I am pondering > the design of a solitaire scorekeeper program. It is just meant to be > an electronic scorekeeper for hands of solitaire that I plan with a > "real" deck of cards, instead of a computer game. I might want to > play and track a variety of solitaire games. And I might want to play > one game for a bit and then switch to another. What you say is a little ambiguous. When you say solitaire, do you mean the specific card game known as "Solitaire", or do you mean the generic term for dozens of different solitaire-type single person card games? When you describe changing games, do you mean changing from (say) "Grandfather's Clock" to "Spider" to "Solitaire", or do you mean start a new game by reshuffling the cards and dealing out a new hand? It might help if you explain how you currently track these games, on paper. -- Steve From robertvstepp at gmail.com Sun Aug 26 22:29:36 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 26 Aug 2018 21:29:36 -0500 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: <20180827004725.GB24160@ando.pearwood.info> References: <20180827004725.GB24160@ando.pearwood.info> Message-ID: On Sun, Aug 26, 2018 at 7:48 PM Steven D'Aprano wrote: > > On Sun, Aug 26, 2018 at 05:38:52PM -0500, boB Stepp wrote: > > > I feel that I may be missing something truly obvious. I am pondering > > the design of a solitaire scorekeeper program. It is just meant to be > > an electronic scorekeeper for hands of solitaire that I plan with a > > "real" deck of cards, instead of a computer game. I might want to > > play and track a variety of solitaire games. And I might want to play > > one game for a bit and then switch to another. > > > What you say is a little ambiguous. When you say solitaire, do you mean > the specific card game known as "Solitaire", or do you mean the generic > term for dozens of different solitaire-type single person card games? > > When you describe changing games, do you mean changing from (say) > "Grandfather's Clock" to "Spider" to "Solitaire", or do you mean > start a new game by reshuffling the cards and dealing out a new hand? There are probably hundreds if not thousands of games that generically fit under the description solitaire. I am only interested in ones that I might play that will have a score result for each hand played with all such scores added together to form a cumulative score for a particular game. > It might help if you explain how you currently track these games, on > paper. The example that I partially gave in my original posting was a game I was told was called "Mastery" when I was a child. In it you count out a pile of 13 cards that is placed to the player's left, face up. Then to the right of this "pile" are placed 4 cards in a row, which is the area where you can play red on black, black on red in descending sequence. Finally you place a single card face up above all of this. In many games, this is where aces are placed and you eventually build up stacks of each suit until you, if fortunate, exhaust the entire deck in this area, where you would have four suit stacks going "A, 2, 3, ... , J, Q, K" in that order. In Mastery, the starting card can be any of the 13 cards. Say it was a 5. Then you would try to get all of the cards into segregated suit stacks where the bottom-most card was the 5 of each suit. So the sequence in a perfectly played game would be "5, 6, 7, ... , J, Q, K, A, 2, 3, 4" In the end any cards in the left-most pile count 2 points against you, while every card in the top-most up to 4 stacks count 1 point for you. So the worst score possible on a hand would be "-26", while the best score possible would be "+52". I hope that this example is clearer than mud! The adult who taught me this particular game when I was a kid kept a spiral bound notebook which he divided into 13 sections, one for each rank of card (A, 2, 3, ... , J, Q, K). Any one of these ranks might start the top-most piles of a particular hand. So for each hand played he would write down the new cumulative score for that section of his notebook. But there are other types of solitaire that I play that might be scored differently. I want my program to work with any such game where a given played hand can have a worst score, a best score, or any integer in between, where the cumulative score over all hands played of that particular game type would reflect the current state of the game. The way the scorekeeper program would work as I currently envisage it would be the player opens an existing game from disk, starts a new game or switches to a game already open. If it is a new game the player will be asked for the minimum possible score per hand, the maximum possible score per hand, and a name for that particular solitaire game he/she wishes to keep track of the cumulative scores for. As for the persistent storage I will have two files per game, a ".cfg" file storing the min and max possible scores (Later if I add features there might be more things in this file.) and a ".csv" file which will retain in played order the date played, time played, and score for the hand played. I figure cumulative scores can be calculated on the fly from this information. Later on if I like what I've done I might add the ability to do various statistical analyses of the hands played, such as average score per hand, number of instances of a particular score or scores, etc. But right now I'm stuck on how to identify each active object with a valid Python identifier. Alan's suggestion of a dictionary of objects sounds like a possibility, but I have no idea if that is the "best " way to do what I am trying to do. -- boB From robertvstepp at gmail.com Sun Aug 26 23:58:34 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 26 Aug 2018 22:58:34 -0500 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: On Sun, Aug 26, 2018 at 6:10 PM Alan Gauld via Tutor wrote: > > On 26/08/18 23:38, boB Stepp wrote: > > > class SolitaireGame(): > > def __init__(self, name): > > self.name = name > > > Say I go with the aforementioned game with 13 separate scores to keep > > track of. The names of these games might be "Two_Mastery", > > "Three_Mastery", ... , "Ace_Mastery". In principle I want 13 objects > > with each one keeping track of each of the above games. Then I might > > want to switch to "Spider_Solitaire", keep track of its score, then go > > to something else, then back to Mastery, etc. How on earth am I to > > generate unique identifiers for each of these SolitaireGame objects in > > a rational way, not knowing in advance moment to moment what type of > > solitaire game I might be playing? > > A dictionary of objects keyed by name? So you are saying do something like: class SolitaireGame(): def __init__(self, name): self.name = name def describe_self(self): print("This game of solitaire is called", self.name, ".") game_objects = {} def make_new_game_object(name): global game_objects game_objects[name[ = SolitaireGame(name) make_new_game_object('Chinese Solitaire') make_new_game_object('Ace Mastery') make_new_game_object('King Mastery') make_new_game_object('Spider') If I run the above in the interactive interpreter: 3.6.6: game_objects {'Chinese Solitaire': <__main__.SolitaireGame object at 0x7f3991d5e400>, 'Ace Mastery': <__main__.SolitaireGame object at 0x7f3991d5e470>, 'King Mastery': <__main__.SolitaireGame object at 0x7f3991d5e438>, 'Spider': <__main__.SolitaireGame object at 0x7f3991d5e4e0>} 3.6.6: game_objects['Spider'].describe_self() This game of solitaire is called Spider. This would seem to work, though I would have to be very careful to not allow the user to create a new game with the same name (Now a key.) which would overwrite an already existing game object. > If using a GUI add the names to a drop down or listbox > to ease later selection. Ultimately I would add a GUI interface. > Does that work for you? If what I wrote above describes what you intend, then yes. > > between them at will. Of course the intent is to persistently store > > these objects on disk upon program closure. > > Maybe JSON for that? Or even a shelve database? I plan to keep this simple. I will use a ".cfg" file to store game configuration information and a ".csv" file to store the actual records of hands played. But I will have to be careful how I generate the base filenames to avoid duplicates and potential nasty user-generated names. Though this project is only meant for my use ... -- boB From mats at wichmann.us Mon Aug 27 00:43:44 2018 From: mats at wichmann.us (Mats Wichmann) Date: Sun, 26 Aug 2018 22:43:44 -0600 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: since your data is somewhat heirarchical - you have records for each game, which can contain from zero to many score records - please consider looking at json or yaml over csv for your persistent storage. they're no harder to program for in Python, and in addition to representing the style of your data better, are more readable as the fields are named. more bulky certainly. On August 26, 2018 9:58:34 PM MDT, boB Stepp wrote: >On Sun, Aug 26, 2018 at 6:10 PM Alan Gauld via Tutor >wrote: >> >> On 26/08/18 23:38, boB Stepp wrote: >> >> > class SolitaireGame(): >> > def __init__(self, name): >> > self.name = name >> >> > Say I go with the aforementioned game with 13 separate scores to >keep >> > track of. The names of these games might be "Two_Mastery", >> > "Three_Mastery", ... , "Ace_Mastery". In principle I want 13 >objects >> > with each one keeping track of each of the above games. Then I >might >> > want to switch to "Spider_Solitaire", keep track of its score, then >go >> > to something else, then back to Mastery, etc. How on earth am I to >> > generate unique identifiers for each of these SolitaireGame objects >in >> > a rational way, not knowing in advance moment to moment what type >of >> > solitaire game I might be playing? >> >> A dictionary of objects keyed by name? > >So you are saying do something like: > >class SolitaireGame(): > def __init__(self, name): > self.name = name > > def describe_self(self): > print("This game of solitaire is called", self.name, ".") > >game_objects = {} >def make_new_game_object(name): > global game_objects > game_objects[name[ = SolitaireGame(name) > >make_new_game_object('Chinese Solitaire') >make_new_game_object('Ace Mastery') >make_new_game_object('King Mastery') >make_new_game_object('Spider') > >If I run the above in the interactive interpreter: >3.6.6: game_objects >{'Chinese Solitaire': <__main__.SolitaireGame object at >0x7f3991d5e400>, 'Ace Mastery': <__main__.SolitaireGame object at >0x7f3991d5e470>, 'King Mastery': <__main__.SolitaireGame object at >0x7f3991d5e438>, 'Spider': <__main__.SolitaireGame object at >0x7f3991d5e4e0>} >3.6.6: game_objects['Spider'].describe_self() >This game of solitaire is called Spider. > >This would seem to work, though I would have to be very careful to not >allow the user to create a new game with the same name (Now a key.) >which would overwrite an already existing game object. > >> If using a GUI add the names to a drop down or listbox >> to ease later selection. > >Ultimately I would add a GUI interface. > >> Does that work for you? > >If what I wrote above describes what you intend, then yes. > >> > between them at will. Of course the intent is to persistently >store >> > these objects on disk upon program closure. >> >> Maybe JSON for that? Or even a shelve database? > >I plan to keep this simple. I will use a ".cfg" file to store game >configuration information and a ".csv" file to store the actual >records of hands played. But I will have to be careful how I generate >the base filenames to avoid duplicates and potential nasty >user-generated names. Though this project is only meant for my use >... > > > >-- >boB >_______________________________________________ >Tutor maillist - Tutor at python.org >To unsubscribe or change subscription options: >https://mail.python.org/mailman/listinfo/tutor -- Sent from my Android device with K-9 Mail. Please excuse my brevity. From alan.gauld at yahoo.co.uk Mon Aug 27 04:43:10 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 27 Aug 2018 09:43:10 +0100 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: On 27/08/18 04:58, boB Stepp wrote: > So you are saying do something like: > > class SolitaireGame(): > def __init__(self, name): > self.name = name > > def describe_self(self): > print("This game of solitaire is called", self.name, ".") > > game_objects = {} > def make_new_game_object(name): > global game_objects > game_objects[name[ = SolitaireGame(name) > > make_new_game_object('Chinese Solitaire') > make_new_game_object('Ace Mastery') > make_new_game_object('King Mastery') Yes, although I'd miss out the function and just populate the dict directly. A single line function doesn't really help much unless its a very complicated line or one that might change regularly (eg storing directly in a database or file rather than in memory). game_objects[name] = SolitaireGame(name) If you are concerned about duplicates just add a guard when you read the name: while True: name = input("Name: ") if name in game_objects: print ("duplicate name, try again") else: break Maybe put that in a function... >> Maybe JSON for that? Or even a shelve database? > > I plan to keep this simple. I will use a ".cfg" file to store game > configuration information and a ".csv" file to store the actual > records of hands played. But I will have to be careful how I generate > the base filenames to avoid duplicates and potential nasty > user-generated names. Though this project is only meant for my use If you go with a single JSON file or shelve you have no worries about name clashes. JSON is specifically designed to store multiple complex object records. And it retains the readability of CSV (unlike shelve). -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From sjeik_appie at hotmail.com Mon Aug 27 05:12:23 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Mon, 27 Aug 2018 09:12:23 +0000 Subject: [Tutor] need help generating table of contents In-Reply-To: References: , Message-ID: From: Tutor on behalf of Peter Otten <__peter__ at web.de> Sent: Friday, August 24, 2018 3:55 PM To: tutor at python.org > The following reshuffle of your code seems to work: > > print('\r\n** Table of contents\r\n') > pattern = '/Title \((.+?)\).+?/Page ([0-9]+)(?:\s+/Count ([0-9]+))?' > > def process(triples, limit=None, indent=0): > ??? for index, (title, page, count) in enumerate(triples, 1): > ??????? title = indent * 4 * ' ' + title > ??????? print(title.ljust(79, ".") + page.zfill(2)) > ??????? if count: > ??????????? process(triples, limit=int(count), indent=indent+1) > ??????? if limit is not None and limit == index: > ?????????? break > > process(iter(re.findall(pattern, toc, re.DOTALL))) Hi Peter, Cameron, Thanks for your replies! The code above indeeed works as intended, but: I don't really understand *why*. I would assign a name to the following line "if limit is not None and limit == index", what would be the most descriptive name? I often use "is_*" names for boolean variables. Would "is_deepest_nesting_level" be a good name? Also, I don't understand why iter() is required here, and why finditer() is not an alternative. I wrote the bookmarks file myself, and the code above is part of a shell script that compiles a large .pdf, with openoffice commandline calls, ghostscript, git, pdftk and python. The human-readable toc and the pdf bookmarks will always be consistent if I only need to edit one file. Thanks again! Albert-Jan From dave at the-hills.org.uk Mon Aug 27 07:14:33 2018 From: dave at the-hills.org.uk (Dave Hill) Date: Mon, 27 Aug 2018 12:14:33 +0100 Subject: [Tutor] Problem compiling code from GitHub Message-ID: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> Hi, As a volunteer on a Welsh Heritage Railway I undertake their Electrical Equipment testing, for which I use a Megger PAT420. This device stores data in 'sqlite', which using Python I can read and generate a number of reports in 'csv' format. I now wish to collate asset data for various locations, and as I use OpenOffice I want to generate an 'ods' document with a 'sheet' for each location. At present I generate a 'csv' file for each location, but as there are 20 locations this is a bit cumbersome. I use the 20 locations as a method to make the handing of over 500 assets somewhat manageable. I have found 'odswriter' on GitHub https://github.com/mmulqueen/odswriter which appears to provide what I want. However, I have come to a halt, due to the limitation of my knowledge. I admit that I am confounded as to where/how to access this code. I am using Python 3.6.4, in IDLE on a PC running windows. I am using the following code as a starting point , Test_ODS#1.py import datetime import decimal ##import odswriter as ods try: ??? from OdsWriter import odswriter as ods except RuntimeError: ??? print("Error importing OdsWriter!") # Single sheet mode with ods.writer(open("test.ods","wb")) as odsfile: ??? odsfile.writerow(["String", "ABCDEF123456", "123456"]) ??? # Lose the 2L below if you want to run this example code on Python 3, Python 3 has no long type. ??? odsfile.writerow(["Float", 1, 123, 123.123, decimal.Decimal("10.321")]) ??? odsfile.writerow(["Date/DateTime", datetime.datetime.now(), datetime.date(1989, 11, 9)]) ??? odsfile.writerow(["Time",datetime.time(13, 37),datetime.time(16, 17, 18)]) ??? odsfile.writerow(["Bool", True, False, True]) ??? odsfile.writerow(["Formula", 1, 2, 3, ods.Formula("IF(A1=2,B1,C1)")]) # Multiple sheet mode with ods.writer(open("test-multi.ods","wb")) as odsfile: ??? bears = odsfile.new_sheet("Bears") ??? bears.writerow(["American Black Bear", "Asiatic Black Bear", "Brown Bear", "Giant Panda", "Qinling Panda", ???????????????????? "Sloth Bear", "Sun Bear", "Polar Bear", "Spectacled Bear"]) ??? sloths = odsfile.new_sheet("Sloths") ??? sloths.writerow(["Pygmy Three-Toed Sloth", "Maned Sloth", "Pale-Throated Sloth", "Brown-Throated Sloth", ???????????????????? "Linneaeus's Two-Twoed Sloth", "Hoffman's Two-Toed Sloth"]) I get the following error Traceback (most recent call last): ? File "C:\Code\Python\ODS_Writer\Test_ODS#1.py", line 5, in ??? from OdsWriter import odswriter as ods ? File "C:\Code\Python\ODS_Writer\OdsWriter.py", line 7, in ??? from . import ods_components ImportError: attempted relative import with no known parent package I have put the code from GitHub in various locations subject to my limited knowledge of Python, but I have no idea what the following extract means, and searching online on & off for two days has proved unfruitful. from __future__ import unicode_literals from zipfile import ZipFile import decimal import datetime from xml.dom.minidom import parseString from . import ods_components from .formula import Formula I understand the use of 'import' and have written my own modules, but from . import ods_components has me floored. Thank you in advance for any help. Dave -------------- next part -------------- import datetime import decimal ##import odswriter as ods try: from OdsWriter import odswriter as ods except RuntimeError: print("Error importing OdsWriter!") # Single sheet mode with ods.writer(open("test.ods","wb")) as odsfile: odsfile.writerow(["String", "ABCDEF123456", "123456"]) # Lose the 2L below if you want to run this example code on Python 3, Python 3 has no long type. odsfile.writerow(["Float", 1, 123, 123.123, decimal.Decimal("10.321")]) odsfile.writerow(["Date/DateTime", datetime.datetime.now(), datetime.date(1989, 11, 9)]) odsfile.writerow(["Time",datetime.time(13, 37),datetime.time(16, 17, 18)]) odsfile.writerow(["Bool", True, False, True]) odsfile.writerow(["Formula", 1, 2, 3, ods.Formula("IF(A1=2,B1,C1)")]) # Multiple sheet mode with ods.writer(open("test-multi.ods","wb")) as odsfile: bears = odsfile.new_sheet("Bears") bears.writerow(["American Black Bear", "Asiatic Black Bear", "Brown Bear", "Giant Panda", "Qinling Panda", "Sloth Bear", "Sun Bear", "Polar Bear", "Spectacled Bear"]) sloths = odsfile.new_sheet("Sloths") sloths.writerow(["Pygmy Three-Toed Sloth", "Maned Sloth", "Pale-Throated Sloth", "Brown-Throated Sloth", "Linneaeus's Two-Twoed Sloth", "Hoffman's Two-Toed Sloth"]) From steve at pearwood.info Mon Aug 27 09:14:57 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 27 Aug 2018 23:14:57 +1000 Subject: [Tutor] Problem compiling code from GitHub In-Reply-To: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> References: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> Message-ID: <20180827131457.GG24160@ando.pearwood.info> Hi Dave, and welcome! On Mon, Aug 27, 2018 at 12:14:33PM +0100, Dave Hill wrote: > I have found 'odswriter' on GitHub > https://github.com/mmulqueen/odswriter which appears to provide what I > want. However, I have come to a halt, due to the limitation of my knowledge. [...] > I get the following error > > Traceback (most recent call last): > ? File "C:\Code\Python\ODS_Writer\Test_ODS#1.py", line 5, in > ??? from OdsWriter import odswriter as ods > ? File "C:\Code\Python\ODS_Writer\OdsWriter.py", line 7, in > ??? from . import ods_components > ImportError: attempted relative import with no known parent package > > I have put the code from GitHub in various locations That sounds like the problem. Some libraries are pretty forgiving about where they are, some not so much. Some come with detailed installation instructions, some don't. This appears to be in the second category of both cases. I would start by carefully deleting the code from Github (or at least moving it out of the way) first, then installing it again. Try installing it using the pip command. Open up a command line console. I think you do this under Windows by typing Ctrl-R ("Run") then entering "cmd", You ought to get a text window with a prompt looking something like this: C:\ % or similar. (If in doubt, ask.) Try entering the command pip --version and if you get an error like "pip not found" or similar, try this: python36 -m ensurepip --default-pip python36 -m pip install --upgrade pip setuptools wheel after which you can then try: pip install odswriter I'll be honest: I don't use pip myself, every time I've tried I get frustrated and end up installing things the old-fashioned manual way which is theoretically "harder" but it works for me. And everyone else swears by pip. (I just swear at it, especially the horrible colours it likes to use.) But if you get any errors, please don't hesitate to copy and paste them here (DON'T take a screen shot) so we can read them and advise you. There's a tutorial here with more detail: https://packaging.python.org/tutorials/installing-packages/ -- Steve From mats at wichmann.us Mon Aug 27 13:51:52 2018 From: mats at wichmann.us (Mats Wichmann) Date: Mon, 27 Aug 2018 11:51:52 -0600 Subject: [Tutor] Problem compiling code from GitHub In-Reply-To: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> References: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> Message-ID: <855dbba1-c2d6-3e41-6d92-b90baa807bbd@wichmann.us> On 08/27/2018 05:14 AM, Dave Hill wrote: > I get the following error > > ?? Traceback (most recent call last): > ??? ? File "C:\Code\Python\ODS_Writer\Test_ODS#1.py", line 5, in > ??? ??? from OdsWriter import odswriter as ods > ??? ? File "C:\Code\Python\ODS_Writer\OdsWriter.py", line 7, in > ??? ??? from . import ods_components > ?? ImportError: attempted relative import with no known parent package > > I have put the code from GitHub in various locations subject to my > limited knowledge of Python, but I have no idea what the following > extract means, and searching online on & off for two days has proved > unfruitful. > > ?? from __future__ import unicode_literals > ?? from zipfile import ZipFile > ?? import decimal > ?? import datetime > ?? from xml.dom.minidom import parseString > > ?? from . import ods_components > ?? from .formula import Formula > > I understand the use of 'import' and have written my own modules, but > from . import ods_components has me floored. > > Thank you in advance for any help. the doc bit you're missing to at least tell you what this is is here: https://docs.python.org/3/tutorial/modules.html#intra-package-references this is tricky ground, however. From __peter__ at web.de Mon Aug 27 14:43:50 2018 From: __peter__ at web.de (Peter Otten) Date: Mon, 27 Aug 2018 20:43:50 +0200 Subject: [Tutor] need help generating table of contents References: Message-ID: Albert-Jan Roskam wrote: > > From: Tutor on behalf > of Peter Otten <__peter__ at web.de> Sent: Friday, August 24, 2018 3:55 PM > To: tutor at python.org > >> The following reshuffle of your code seems to work: >> >> print('\r\n** Table of contents\r\n') >> pattern = '/Title \((.+?)\).+?/Page ([0-9]+)(?:\s+/Count ([0-9]+))?' >> >> def process(triples, limit=None, indent=0): >> for index, (title, page, count) in enumerate(triples, 1): >> title = indent * 4 * ' ' + title >> print(title.ljust(79, ".") + page.zfill(2)) >> if count: >> process(triples, limit=int(count), indent=indent+1) >> if limit is not None and limit == index: >> break >> >> process(iter(re.findall(pattern, toc, re.DOTALL))) > > Hi Peter, Cameron, > > Thanks for your replies! The code above indeeed works as intended, but: I > don't really understand *why*. I would assign a name to the following line > "if limit is not None and limit == index", what would be the most > descriptive name? I often use "is_*" names for boolean variables. Would > "is_deepest_nesting_level" be a good name? No, it's not necessarily the deepest level. Every subsection eventually ends at this point; so you might call it reached_end_of_current_section Or just 'limit' ;) The None is only there for the outermost level where no /Count is provided. In this case the loop is exhausted. If you find it is easier to understand you can calculate the outer count aka limit as the number of matches - sum of counts: def process(triples, section_length, indent=0): for index, (title, page, count) in enumerate(triples, 1): title = indent * 4 * ' ' + title print(title.ljust(79, ".") + page.zfill(2)) if count: process(triples, section_length=int(count), indent=indent+1) if section_length == index: break triples = re.findall(pattern, toc, re.DOTALL) toplevel_section_length = ( len(triples) - sum(int(c or 0) for t, p, c in triples) ) process(iter(triples), toplevel_section_length) Just for fun here's one last variant that does away with the break -- and thus the naming issue -- completely: def process(triples, limit=None, indent=0): for title, page, count in itertools.islice(triples, limit): title = indent * 4 * ' ' + title print(title.ljust(79, ".") + page.zfill(2)) if count: process(triples, limit=int(count), indent=indent+1) Note that islice(items, None) does the right thing: >>> list(islice("abc", None)) ['a', 'b', 'c'] > Also, I don't understand why iter() is required here, and why finditer() > is not an alternative. finditer() would actually work -- I didn't use it because I wanted to make as few changes as possible to your code. What does not work is a list like the result of findall(). This is because the inner for loops (i. e. the ones in the nested calls of process) are supposed to continue the iteration instead of restarting it. A simple example to illustrate the difference: >>> s = "abcdefg" >>> for k in range(3): ... print("===", k, "===") ... for i, v in enumerate(s): ... print(v) ... if i == 2: break ... === 0 === a b c === 1 === a b c === 2 === a b c >>> s = iter("abcdefg") >>> for k in range(3): ... print("===", k, "===") ... for i, v in enumerate(s): ... print(v) ... if i == 2: break ... === 0 === a b c === 1 === d e f === 2 === g From robertvstepp at gmail.com Mon Aug 27 21:53:48 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Mon, 27 Aug 2018 20:53:48 -0500 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: On Mon, Aug 27, 2018 at 3:44 AM Alan Gauld via Tutor wrote: > > On 27/08/18 04:58, boB Stepp wrote: > >> Maybe JSON for that? Or even a shelve database? > > > > I plan to keep this simple. I will use a ".cfg" file to store game > > configuration information and a ".csv" file to store the actual > > records of hands played. But I will have to be careful how I generate > > the base filenames to avoid duplicates and potential nasty > > user-generated names. Though this project is only meant for my use > > > If you go with a single JSON file or shelve you have > no worries about name clashes. JSON is specifically > designed to store multiple complex object records. > And it retains the readability of CSV (unlike shelve). Wouldn't a single JSON file be wasteful? If I used this program for a couple of years or so and habitually played a lot of solitaire, that would be a lot of stuff to load into RAM when on any given solitaire session I might only play one to three kinds of solitaire. But perhaps I am misunderstanding JSON's capabilities as I only have a cursory knowledge of it from considering it for other projects. OTOH, even if I loaded into RAM all games I might have ever played I doubt I would stress out my RAM capacity, so perhaps this is a non-issue for this type of program on any modern computer. -- boB From alan.gauld at yahoo.co.uk Tue Aug 28 03:15:48 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 28 Aug 2018 08:15:48 +0100 Subject: [Tutor] How to have unique identifiers for multiple object instances of a given class? In-Reply-To: References: Message-ID: On 28/08/18 02:53, boB Stepp wrote: > Wouldn't a single JSON file be wasteful? If I used this program for a > couple of years or so and habitually played a lot of solitaire, that > would be a lot of stuff to load into RAM when on any given solitaire > session I might only play one to three kinds of solitaire. It shouldn't be any more wasteful than if you used separate files. Either you have to load up every file you ever saved or you have some criteria that prevents you loading all of them. The same with a JSON file. Either you load every record in the file or you have some criteria that lets you load a subset. You might want to eventually have some kind of archive function that offloads old games to a separate file, just to keep initial load times down but that's probably not an issue in the short term. > perhaps I am misunderstanding JSON's capabilities as I only have a > cursory knowledge of it from considering it for other projects. Think of it like a file based dictionary. You only instantiate the objects you need. You load objects based on the key. How you identify which objects you need at startup is the clever bit. You haven't told us enough about your workflow for us to suggest a solution there. But the same issue applies whether you use separate files per game or session or a single JSON file. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From sjeik_appie at hotmail.com Tue Aug 28 06:14:37 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Tue, 28 Aug 2018 10:14:37 +0000 Subject: [Tutor] need help generating table of contents In-Reply-To: References: , Message-ID: From: Tutor on behalf of Peter Otten <__peter__ at web.de> Sent: Monday, August 27, 2018 6:43 PM To: tutor at python.org Subject: Re: [Tutor] need help generating table of contents ? Albert-Jan Roskam wrote: > > From: Tutor on behalf > of Peter Otten <__peter__ at web.de> Sent: Friday, August 24, 2018 3:55 PM > To: tutor at python.org > >> The following reshuffle of your code seems to work: >> >> print('\r\n** Table of contents\r\n') >> pattern = '/Title \((.+?)\).+?/Page ([0-9]+)(?:\s+/Count ([0-9]+))?' >> >> def process(triples, limit=None, indent=0): >> for index, (title, page, count) in enumerate(triples, 1): >> title = indent * 4 * ' ' + title >> print(title.ljust(79, ".") + page.zfill(2)) >> if count: >> process(triples, limit=int(count), indent=indent+1) >> if limit is not None and limit == index: >>? break >> >> process(iter(re.findall(pattern, toc, re.DOTALL))) > > Hi Peter, Cameron, > > Thanks for your replies! The code above indeeed works as intended, but: I > don't really understand *why*. I would assign a name to the following line > "if limit is not None and limit == index", what would be the most > descriptive name? I often use "is_*" names for boolean variables. Would > "is_deepest_nesting_level" be a good name? > No, it's not necessarily the deepest level. Every subsection eventually ends > at this point; so you might call it reached_end_of_current_section > > Or just 'limit' ;) LOL. Ok, now I get it :-) > The None is only there for the outermost level where no /Count is provided. > In this case the loop is exhausted. > > If you find it is easier to understand you can calculate the outer count aka > limit as the number of matches - sum of counts: > >> Also, I don't understand why iter() is required here, and why finditer() > >is not an alternative. >finditer() would actually work -- I didn't use it because I wanted to make > as few changes as possible to your code. What does not work is a list like >the result of findall(). This is because the inner for loops (i. e. the ones >in the nested calls of process) are supposed to continue the iteration >instead of restarting it. A simple example to illustrate the difference: Ah, the triples cannot be unpacked inside the "for" line of the loop. This works: def process(triples, limit=None, indent=0): for index, triple in enumerate(triples, 1): title, page, count = triple.groups() # unpack it here title = indent * 4 * ' ' + title print(title.ljust(79, ".") + page.zfill(2)) if count: process(triples, limit=int(count), indent=indent+1) if limit is not None and limit == index: break process(re.finditer(pattern, toc, re.DOTALL)) If I don't do this, I get this error: File "Q:/toc/toc.py", line 64, in process(re.finditer(pattern, toc, re.DOTALL)) File "Q:/Ctoc/toc.py", line 56, in process for index, (title, page, count) in enumerate(triples, 1): TypeError: '_sre.SRE_Match' object is not iterable Process finished with exit code 1 Thanks again Peter! Very insightful! Albert-Jan From dave at the-hills.org.uk Tue Aug 28 12:30:55 2018 From: dave at the-hills.org.uk (Dave Hill) Date: Tue, 28 Aug 2018 17:30:55 +0100 Subject: [Tutor] Problem compiling code from GitHub In-Reply-To: <20180827131457.GG24160@ando.pearwood.info> References: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> <20180827131457.GG24160@ando.pearwood.info> Message-ID: <222d97c1-e37c-43b6-73c4-3a824d1b8318@the-hills.org.uk> I did as suggested but with the same result. I am now looking at extracting the code from the the separate files to form a single module, and hopefully get a result. On 27/08/2018 14:14, Steven D'Aprano wrote: > Hi Dave, and welcome! > > > On Mon, Aug 27, 2018 at 12:14:33PM +0100, Dave Hill wrote: > >> I have found 'odswriter' on GitHub >> https://github.com/mmulqueen/odswriter which appears to provide what I >> want. However, I have come to a halt, due to the limitation of my knowledge. > [...] > > >> I get the following error >> >> Traceback (most recent call last): >> ? File "C:\Code\Python\ODS_Writer\Test_ODS#1.py", line 5, in >> ??? from OdsWriter import odswriter as ods >> ? File "C:\Code\Python\ODS_Writer\OdsWriter.py", line 7, in >> ??? from . import ods_components >> ImportError: attempted relative import with no known parent package >> >> I have put the code from GitHub in various locations > That sounds like the problem. Some libraries are pretty forgiving about > where they are, some not so much. Some come with detailed installation > instructions, some don't. > > This appears to be in the second category of both cases. > > I would start by carefully deleting the code from Github (or at least > moving it out of the way) first, then installing it again. > > Try installing it using the pip command. Open up a command line console. > I think you do this under Windows by typing Ctrl-R ("Run") then entering > "cmd", You ought to get a text window with a prompt looking something > like this: > > C:\ % > > or similar. (If in doubt, ask.) > > Try entering the command > > pip --version > > and if you get an error like "pip not found" or similar, try this: > > python36 -m ensurepip --default-pip > python36 -m pip install --upgrade pip setuptools wheel > > after which you can then try: > > pip install odswriter > > I'll be honest: I don't use pip myself, every time I've tried I get > frustrated and end up installing things the old-fashioned manual way > which is theoretically "harder" but it works for me. And everyone else > swears by pip. (I just swear at it, especially the horrible colours it > likes to use.) > > But if you get any errors, please don't hesitate to copy and paste them > here (DON'T take a screen shot) so we can read them and advise you. > > > There's a tutorial here with more detail: > > https://packaging.python.org/tutorials/installing-packages/ > > > > From tara_38 at live.com Tue Aug 28 19:30:35 2018 From: tara_38 at live.com (Tara 38) Date: Tue, 28 Aug 2018 23:30:35 +0000 Subject: [Tutor] Contour Plots Message-ID: Hi, I wonder if someone can give me some advice? I need to build a contour plot (ideally with Seaborn) in python. The plot would document text data. I cannot work out how I need to convert the data file (currently csv file) so that I have 3 variables that I can then plot as a contour map and visualize in Seaborn. Really stuck as to where to even start. Thanks, Tara [https://ipmcdn.avast.com/images/icons/icon-envelope-tick-green-avg-v1.png] Virus-free. www.avg.com From robertvstepp at gmail.com Tue Aug 28 22:04:26 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Tue, 28 Aug 2018 21:04:26 -0500 Subject: [Tutor] Contour Plots In-Reply-To: References: Message-ID: Welcome Tara! On Tue, Aug 28, 2018 at 6:46 PM Tara 38 wrote: > > Hi, > > > I wonder if someone can give me some advice? I need to build a contour plot (ideally with Seaborn) in python. The plot would document text data. I cannot work out how I need to convert the data file (currently csv file) so that I have 3 variables that I can then plot as a contour map and visualize in Seaborn. > > > Really stuck as to where to even start. You really did not give many details or your Python background and knowledge, so it is difficult to know exactly what you need help with. But from your description as is, it sounds like your immediate problem is extracting data from your csv file. Python 2 and 3 have a csv module to facilitate handling this type of file. The Python 3 docs for it are at https://docs.python.org/3/library/csv.html A Python csv tutorial (after Googling) can be found at https://www.blog.pythonlibrary.org/2014/02/26/python-101-reading-and-writing-csv-files/ There are many others you can find via a search if you don't like that one. If your problems lie with generating Seaborn plots another search found their official tutorial at https://seaborn.pydata.org/tutorial.html If the above does not sufficiently help then you will have to provide additional information as to what exactly you are trying to do, how are you trying to do it, where are you getting stuck, etc. HTH! -- boB From __peter__ at web.de Wed Aug 29 08:14:09 2018 From: __peter__ at web.de (Peter Otten) Date: Wed, 29 Aug 2018 14:14:09 +0200 Subject: [Tutor] Problem compiling code from GitHub References: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> <20180827131457.GG24160@ando.pearwood.info> <222d97c1-e37c-43b6-73c4-3a824d1b8318@the-hills.org.uk> Message-ID: Dave Hill wrote: > I did as suggested but with the same result. Make sure that your script is *not* in the same directory as ODSWriter.py and that the directory containing ODSWriter is *not* in sys.path. Then try again. From oscar.j.benjamin at gmail.com Wed Aug 29 09:04:49 2018 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Wed, 29 Aug 2018 14:04:49 +0100 Subject: [Tutor] Problem compiling code from GitHub In-Reply-To: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> References: <64432655-d3e4-2ad8-262d-5df257941b6a@the-hills.org.uk> Message-ID: On Mon, 27 Aug 2018 at 13:18, Dave Hill wrote: > > I have found 'odswriter' on GitHub > https://github.com/mmulqueen/odswriter which appears to provide what I > want. However, I have come to a halt, due to the limitation of my knowledge. > > I admit that I am confounded as to where/how to access this code. There are two ways. The code is there in github because that's where the author(s) are saving their work on it and where people could contribute to it. Normally as a "user" of the odswriter code you wouldn't access it from there. If you did want to access it from github in order to use the code you would normally use the git program to download it: $ git clone https://github.com/mmulqueen/odswriter Alternatively you can download the .zip file from github using your browser and extract it. Either way you then need to *install* the package to use it: $ cd odswriter $ python setup.py install However as I said before someone who simply wants to use the odswriter code (and not contribute to writing it) would not normally access the code from github since Python has a better place for this which is PyPI. You can see the PyPI page for odswriter here: https://pypi.org/project/odswriter/ Again though you wouldn't normally download the code from PyPI using the web browser. Python comes with a program called pip which can download and install it for you. So the command is: $ pip install odswriter I don't know why Steve has difficulty with that but this is the easiest, fastest, officially-recommended etc. way to install Python packages. > I am using Python 3.6.4, in IDLE on a PC running windows. > > I am using the following code as a starting point , Test_ODS#1.py > > import datetime > import decimal > ##import odswriter as ods > try: > from OdsWriter import odswriter as ods > except RuntimeError: > print("Error importing OdsWriter!") I have just installed odswriter in Python 3.6, on Linux, using pip and I get this: >>> from OdsWriter import odswriter as ods Traceback (most recent call last): File "", line 1, in ModuleNotFoundError: No module named 'OdsWriter' However if I instead write >>> from odswriter import ODSWriter then it works fine. The package name odswriter should be all lower-case. This may not show an error on Windows because you may be using a case-insensitive filesystem but you should fix it anyway. The class-name ODSWriter needs to exactly match each upper and lower-case letter because Python is much fussier than Windows file systems. I think that misspelling the capitals in a package name can lead to import problems although I don't know if that explains the problem you're having. Most likely that is because you haven't "installed" the code correctly. -- Oscar From robertvstepp at gmail.com Wed Aug 29 23:44:07 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Aug 2018 22:44:07 -0500 Subject: [Tutor] OT: How to automate the setting of file permissions for all files in a collection of programs? Message-ID: At work I have accumulated a motley collection of programs I have written since I started around 2012. These all run on the Solaris OS. As long-time readers of my past ramblings may recall, I am not allowed to install any outside programs on this Solaris system, but I am allowed to write my own programs to my heart's content, using only whatever programming-related tools that happen to be installed on a rather bare-bones OS install. We have just recently completed upgrades on hardware, Solaris and treatment planning software. On the good news side we went from the vi editor to Vim/gVim; from Python 2.4 to 2.7; in addition to Tkinter there is now a Python interface to GTK; went from no SQLite to having it; and a few other goodies that currently slip my mind. But on the bad side the only version control system installed, SCCS (RIP!) went bye-bye with _nothing_ to replace it. And as usual the radiation therapy planning software we use was upgraded from version 9.10 to 16.2, breaking several of my programs, requiring updates on my part that I recently completed. So as to not lose the benefits of a version control system, I have installed Git on my windows PC. My current workflow now has gotten more complex, and I'm sure can be improved by those thinking more clearly than I (And surely more knowledgeable!), and is as follows: 1) Using CuteFTP copy all of my original working code (Now with problems due to the planning software upgrade.) to my windows PC. 2) Put this code under Git version control. 3) Create a development branch. 4) FTP this back to Solaris for code repair, testing, etc. BUT! This process has changed all of the Unix file permissions on what are (For me.) many files, some planning system proprietary scripting files, some Perl files, some shell script files and some Python files. So before I can do anything further I must go through all of these files and change their permissions to the values I need them to be. This is quite tedious and error prone. So I wish to either fix the process, or, failing that, automate the process of correcting the file permissions. If there is a way in this CuteFTP software to maintain file permissions in this back-and-forth transferring between a Windows and Solaris environment, I have yet to find it in the software's help (Though I have not yet had much time to invest in this search, so I may not have found it yet.). It occurs to me that in theory it should be possible to automate this either with a shell script or a Python program. Is there a standard way of handling this sort of thing? Bear in mind that if a typical solution would require the installation of a software package in the Solaris environment, I am not allowed to do so. I am not allowed to use Python pip either. Strange rules ... -- boB From cs at cskk.id.au Thu Aug 30 00:49:32 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 30 Aug 2018 14:49:32 +1000 Subject: [Tutor] OT: How to automate the setting of file permissions for all files in a collection of programs? In-Reply-To: References: Message-ID: <20180830044932.GA98896@cskk.homeip.net> On 29Aug2018 22:44, boB Stepp wrote: >So as to not lose the benefits of a version control system, I have >installed Git on my windows PC. My current workflow now has gotten >more complex, and I'm sure can be improved by those thinking more >clearly than I (And surely more knowledgeable!), and is as follows: > >1) Using CuteFTP copy all of my original working code (Now with >problems due to the planning software upgrade.) to my windows PC. >2) Put this code under Git version control. >3) Create a development branch. >4) FTP this back to Solaris for code repair, testing, etc. BUT! >This process has changed all of the Unix file permissions on what are >(For me.) many files, some planning system proprietary scripting >files, some Perl files, some shell script files and some Python files. >So before I can do anything further I must go through all of these >files and change their permissions to the values I need them to be. >This is quite tedious and error prone. So I wish to either fix the >process, or, failing that, automate the process of correcting the file >permissions. > >If there is a way in this CuteFTP software to maintain file >permissions in this back-and-forth transferring between a Windows and >Solaris environment, I have yet to find it in the software's help >(Though I have not yet had much time to invest in this search, so I >may not have found it yet.). > >It occurs to me that in theory it should be possible to automate this >either with a shell script or a Python program. > >Is there a standard way of handling this sort of thing? Bear in mind >that if a typical solution would require the installation of a >software package in the Solaris environment, I am not allowed to do >so. I am not allowed to use Python pip either. Strange rules ... Does rsync exist on your Solaris system? Can you get rsync and ssh on your Windows system? The "standard" UNIX solution to reproduce a directory somewhere is rsync these days, which will work over ssh (by default) if the target is remote. IIRC, git doesn't track file permissions, so you can't just "export" from your WIndows git (or some mirror elsewhere). So: do you have rsync? Do you have ssh from your PC to the Solaris box? Cheers, Cameron Simpson From matthew.polack at htlc.vic.edu.au Wed Aug 29 22:56:03 2018 From: matthew.polack at htlc.vic.edu.au (Matthew Polack) Date: Thu, 30 Aug 2018 12:56:03 +1000 Subject: [Tutor] A Python program to Summarise weather results? Message-ID: Hi, We have a spreadsheet from a local weather station.....it summarises the amount of rainfall per day since 1863. http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=1863&p_c=-1249186659&p_stn_num=079028 We'd love to be able to summarise this into years eg. Total rainfall of 1863, 1864 all the way through to 2018. Would Python be able to do this using the csv file? Thanks, Matt Matthew Polack | Teacher [image: Emailbanner3.png] Trinity Drive | PO Box 822 Horsham Victoria 3402 p. 03 5382 2529 m. 0402456854 e. matthew.polack at htlc.vic.edu.au w. www.htlc.vic.edu.au -- **Disclaimer: *Whilst every attempt has been made to ensure that material contained in this email is free from computer viruses or other defects, the attached files are provided, and may only be used, on the basis that the user assumes all responsibility for use of the material transmitted. This email is intended only for the use of the individual or entity named above and may contain information that is confidential and privileged. If you are not the intended recipient, please note that any dissemination, distribution or copying of this email is strictly prohibited. If you have received this email in error, please notify us immediately by return email or telephone +61 3 5382 2529**?and destroy the original message.* From rls4jc at gmail.com Wed Aug 29 19:09:37 2018 From: rls4jc at gmail.com (Roger Lea Scherer) Date: Wed, 29 Aug 2018 16:09:37 -0700 Subject: [Tutor] localhosting Message-ID: I'm trying to implement a local host. My instructions tell me to type the following command in the command line, make sure I'm in the "www" folder (which I am and not a subfolder, although there is a subfolder "cgi-bin") and then run this: python3 -m http.server --cgi 8000 I'm running Anaconda in Windows 10. I get an error: 'python3' is not recognized as an internal or external command, operable program or batch file. But this is the folder that I thought Python 3.6 was in. I tried Windows PowerShell and received this error message: python3 : The term 'python3' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. So how do I correct this? I suspect python3 isn't in this folder. I know I have python3 because I run python3.6 shell practically every day. I've looked in the Program Files folder, came up empty as far as python is concerned, but I don't know where else to look? Or if this is not the correct forum, can you please (re)direct me to the correct one? Thank you. -- Roger Lea Scherer 623.255.7719 *Strengths:* Input, Strategic, Responsibility, Learner, Ideation From alan.gauld at yahoo.co.uk Thu Aug 30 04:08:11 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 30 Aug 2018 09:08:11 +0100 Subject: [Tutor] OT: How to automate the setting of file permissions for all files in a collection of programs? In-Reply-To: References: Message-ID: On 30/08/18 04:44, boB Stepp wrote: > good news side we went from the vi editor to Vim/gVim; from Python 2.4 > to 2.7; in addition to Tkinter there is now a Python interface to GTK; > went from no SQLite to having it; and a few other goodies that Hooray!!! > system installed, SCCS (RIP!) went bye-bye with _nothing_ to replace Boooo. > 1) Using CuteFTP copy all of my original working code (Now with > problems due to the planning software upgrade.) to my windows PC. > 2) Put this code under Git version control. This should be a one-off operation. > 3) Create a development branch. > 4) FTP this back to Solaris for code repair, testing, etc. Have you installed cygwin (or the Microsoft Linux subsystem) on your PC? If so have you trioed working on your files on the PC and only ftp'ing the "working" files to Solaris? At the very least cygwin would allow you to run X Windows on your PC and display the Solaris programs on your PC screen. It should also provide tools like rsync and ssh at the PC end. (As per Camerons mail, rsync is by far the best tool for syncing file systems across machines) > This process has changed all of the Unix file permissions That is inherent in using version control systems. > So before I can do anything further I must go through all of these > files and change their permissions to the values I need them to be. > This is quite tedious and error prone. I'd opt for a shell script based on the find command You can of course do it with Python but a shell script is the more obvious tool for this kind of operation. > If there is a way in this CuteFTP software to maintain file > permissions in this back-and-forth transferring between a Windows and I don't know CuteFTP but rsync definitely can. One of its zillions of options. > software package in the Solaris environment, I am not allowed to do > so. I am not allowed to use Python pip either. Strange rules ... Not that odd in a corporate environment, I was still using Python 1.3 in 2002 for similar reasons on one of our work servers. But there is a 50/5-0 chance the latest Solaris upgrade will have included rsync. Even if it hasn't, if you can mount a Solaris drive on your PC then you can still use rsync from your PC (via cygwin). Is that an option? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at yahoo.co.uk Thu Aug 30 04:54:23 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 30 Aug 2018 09:54:23 +0100 Subject: [Tutor] localhosting In-Reply-To: References: Message-ID: On 30/08/18 00:09, Roger Lea Scherer wrote: > I'm trying to implement a local host. My instructions tell me to type the > following command in the command line, make sure I'm in the "www" folder So this is not the folder where python3 is installed. (See below) > python3 -m http.server --cgi 8000 > I'm running Anaconda in Windows 10. I get an error: 'python3' is not > recognized as an internal or external command, operable program or batch > file. > But this is the folder that I thought Python 3.6 was in. you said you were in www which is not where Python should be installed. It is likely that Python is not in your system PATH. You need to find out where it is installed and add it. In a standard Python install it would either be in C:\PROGRAM FILES\PYTHON or C:\PYTHON But Anaconda (version please?) could use its own path such as C:\ANACONDA\PYTHON > So how do I correct this? I suspect python3 isn't in this folder. I know I > have python3 because I run python3.6 shell practically every day. How do you run it? >From a command line or via a menu/shortcut? > looked in the Program Files folder, came up empty as far as python is > concerned, but I don't know where else to look? Try using Windows search tool and look for a file called python*.exe > Or if this is not the correct forum, can you please (re)direct me to the > correct one? This is OK, although you might try the Anaconda folks too since they will know more about how/where Anaconda installs python and sets up[ default paths. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Thu Aug 30 05:02:07 2018 From: __peter__ at web.de (Peter Otten) Date: Thu, 30 Aug 2018 11:02:07 +0200 Subject: [Tutor] A Python program to Summarise weather results? References: Message-ID: Matthew Polack wrote: > Hi, > > We have a spreadsheet from a local weather station.....it summarises the > amount of rainfall per day since 1863. > > http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=1863&p_c=-1249186659&p_stn_num=079028 > > We'd love to be able to summarise this into years eg. Total rainfall of > 1863, 1864 all the way through to 2018. > > Would Python be able to do this using the csv file? Yes. Python has powerful tools to make this concise, like csv.DictReader() and itertools.groupby(), or -- even more highlevel -- pandas. But you want to learn Python, don't you? Therefore I recommend that you try to solve this with just open() and a for loop to read the lines, and the str.split() method to break the lines into fields. With 'if ....' you check whether the year has changed so that you need to print the current total and reset the total rainfall. Give it a try, see how far you get, and we'll help you over the obstacles once you can present some rudimentary code. From alan.gauld at yahoo.co.uk Thu Aug 30 04:59:09 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 30 Aug 2018 09:59:09 +0100 Subject: [Tutor] A Python program to Summarise weather results? In-Reply-To: References: Message-ID: On 30/08/18 03:56, Matthew Polack wrote: > Hi, > > We have a spreadsheet from a local weather station.....it summarises the > amount of rainfall per day since 1863. > > http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=1863&p_c=-1249186659&p_stn_num=079028 > > We'd love to be able to summarise this into years eg. Total rainfall of > 1863, 1864 all the way through to 2018. > > Would Python be able to do this using the csv file? Absolutely, the csv module will let you read the data. How you process it is then up to you. If its only the year field you want to filter by consider loading it into a dictionary using the year as the key. Personally, I'd put it into a SQLite database and use SQL to do the report generation (either from Python or via the SQLIte command line tool). That lets you explore the data in many more interesting ways. But learning SQL might be a step too far at this juncture. :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cs at cskk.id.au Thu Aug 30 05:30:31 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 30 Aug 2018 19:30:31 +1000 Subject: [Tutor] OT: How to automate the setting of file permissions for all files in a collection of programs? In-Reply-To: References: Message-ID: <20180830093031.GA625@cskk.homeip.net> On 30Aug2018 09:08, Alan Gauld wrote: >On 30/08/18 04:44, boB Stepp wrote: [...] >> 4) FTP this back to Solaris for code repair, testing, etc. [...] >> This process has changed all of the Unix file permissions > >That is inherent in using version control systems. Not really. I suspect FTP may not be preserving permissions across the transfer (no proof though). But git doesn't preserve file permissions as pat of the state. Personally I use mercurial which does include the permissions in the state. But there's also the issue of Windows permissions versus UNIX permissions. [...] >> If there is a way in this CuteFTP software to maintain file >> permissions in this back-and-forth transferring between a Windows and CuteFTP's web site says it can use SFTP (ssh's ftp-ish protocol, which can preserve permissions). https://www.globalscape.com/cuteftp >I don't know CuteFTP but rsync definitely can. One of >its zillions of options. The option is -p (permissions). >> software package in the Solaris environment, I am not allowed to do >> so. I am not allowed to use Python pip either. Strange rules ... > >Not that odd in a corporate environment, I was still using >Python 1.3 in 2002 for similar reasons on one of our work >servers. > >But there is a 50/5-0 chance the latest Solaris upgrade >will have included rsync. > >Even if it hasn't, if you can mount a Solaris drive on your >PC then you can still use rsync from your PC (via cygwin). >Is that an option? If he can mount a Solaris drive (NFS or SMB) he can just copy the files :-) Cheers, Cameron Simpson From alan.gauld at yahoo.co.uk Thu Aug 30 06:41:51 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 30 Aug 2018 11:41:51 +0100 Subject: [Tutor] OT: How to automate the setting of file permissions for all files in a collection of programs? In-Reply-To: <20180830093031.GA625@cskk.homeip.net> References: <20180830093031.GA625@cskk.homeip.net> Message-ID: On 30/08/18 10:30, Cameron Simpson wrote: >> That is inherent in using version control systems. > ...> state. Personally I use mercurial which does include the permissions in the > state. Ah, interesting. I've never found a VC system that preserved permissions. Usually they zap everything to read-only on first export. Then change them to read-write when you check out etc, then back to read-only on checkin. I never assume anything about permissions from a VC system and always set them as they should be in the make file or installer. > But there's also the issue of Windows permissions versus UNIX permissions. Very true aqnd that varies by file system too. (FAT v NTFS etc) > If he can mount a Solaris drive (NFS or SMB) he can just copy the files :-) Yes, but rsync will ensure only the changed files get copied. Although I think DOS XCOPY can maybe do that too, which might be another option... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From mats at wichmann.us Thu Aug 30 08:59:28 2018 From: mats at wichmann.us (Mats Wichmann) Date: Thu, 30 Aug 2018 06:59:28 -0600 Subject: [Tutor] localhosting In-Reply-To: References: Message-ID: <55925a4a-ceb0-2a43-33fc-bb649134ba39@wichmann.us> On 08/30/2018 02:54 AM, Alan Gauld via Tutor wrote: > On 30/08/18 00:09, Roger Lea Scherer wrote: >> I'm trying to implement a local host. My instructions tell me to type the >> following command in the command line, make sure I'm in the "www" folder > > So this is not the folder where python3 is installed. (See below) > >> python3 -m http.server --cgi 8000 > >> I'm running Anaconda in Windows 10. I get an error: 'python3' is not >> recognized as an internal or external command, operable program or batch >> file. >> But this is the folder that I thought Python 3.6 was in. > > you said you were in www which is not where Python should > be installed. > > It is likely that Python is not in your system PATH. > You need to find out where it is installed and add it. > In a standard Python install it would either be in > C:\PROGRAM FILES\PYTHON or > C:\PYTHON > > But Anaconda (version please?) could use its own path > such as > > C:\ANACONDA\PYTHON > >> So how do I correct this? I suspect python3 isn't in this folder. I know I >> have python3 because I run python3.6 shell practically every day. > > How do you run it? >>From a command line or via a menu/shortcut? > >> looked in the Program Files folder, came up empty as far as python is >> concerned, but I don't know where else to look? Several things that could help: you can ask python itself to tell you where it is, since you say python works for you. >>> import sys >>> print(sys.executable) the standard Windows python defaults to a "user install", so it could be in a place like {yourhomdirectory}/AppData/Local/Programs/Python Anaconda, as Alan says, likely puts it somewhere different. Python 3 isn't named python3 on Windows unless you take steps to make it so, it's just called python. So modify your instructions accordingly. Also on Windows, if it was installed, there is a separate thing called the Python Launcher, which lets you run the command "py" which typically gets put in a place that is always found, and avoids the fiddling with getting Python itself into your PATH. But I'm unsure whether the Anaconda install actually installs that. You could try... just type: py From rafael.knuth at gmail.com Thu Aug 30 13:41:28 2018 From: rafael.knuth at gmail.com (Rafael Knuth) Date: Thu, 30 Aug 2018 19:41:28 +0200 Subject: [Tutor] SQL querying Message-ID: Can I do SQL querying in Python? What packages do I need for that purpose? (specifically for mySQL) Thanks. From mats at wichmann.us Thu Aug 30 22:01:53 2018 From: mats at wichmann.us (Mats Wichmann) Date: Thu, 30 Aug 2018 20:01:53 -0600 Subject: [Tutor] SQL querying In-Reply-To: References: Message-ID: <14e19c9c-62e3-e0a6-bb5c-9786952a4ff3@wichmann.us> On 08/30/2018 11:41 AM, Rafael Knuth wrote: > Can I do SQL querying in Python? > What packages do I need for that purpose? (specifically for mySQL) Thanks. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > yeah, it works fine. there are actually some competing options (you wanted one simple answer?). Oracle has an "official" connector (search for that). There's MySQLdb, which I've used a fair bit. There's a pure-python version called pymysql. And if you are going to get into advanced uses, there's a lovely bit of code called SQL Alchemy. From darylheppner at gmail.com Thu Aug 30 19:41:05 2018 From: darylheppner at gmail.com (Daryl Heppner) Date: Thu, 30 Aug 2018 19:41:05 -0400 Subject: [Tutor] SQL querying In-Reply-To: References: Message-ID: Haven't worked with mySQL but MS SQL Server (and any other ODBC connection) should connect importing pyodbc. Good luck! Daryl On Thu, Aug 30, 2018 at 6:26 PM Rafael Knuth wrote: > > Can I do SQL querying in Python? > What packages do I need for that purpose? (specifically for mySQL) Thanks. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From nmadhok at g.clemson.edu Thu Aug 30 19:11:01 2018 From: nmadhok at g.clemson.edu (Nitin Madhok) Date: Thu, 30 Aug 2018 19:11:01 -0400 Subject: [Tutor] SQL querying In-Reply-To: References: Message-ID: Rafael, Yes you can absolutely do that. You can use the MySQL connector (https://dev.mysql.com/doc/connector-python/en/connector-python-introduction.html ) or use one of the following modules: * MySQLdb (comes from package MySQL-python) * mysql.connector (comes from package mysql-connector-python) * pymysql (comes from package PyMySQL) You can install them by doing: pip install For example: pip install mysql-connector -- Thanks, Nitin Madhok Clemson University CONFIDENTIALITY NOTICE This e-mail, and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain privileged and/or confidential information. If you are not the intended recipient of this e-mail, any dissemination, distribution or copying of this e-mail, and any attachments thereto, is strictly prohibited. If you have received this e-mail in error, please immediately notify the sender by e-mail or telephone and permanently delete all copies of this e-mail and any attachments. > On Aug 30, 2018, at 1:41 PM, Rafael Knuth wrote: > > Can I do SQL querying in Python? > What packages do I need for that purpose? (specifically for mySQL) Thanks. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor