From manpritsinghece at gmail.com Sat Jan 1 06:48:34 2022 From: manpritsinghece at gmail.com (Manprit Singh) Date: Sat, 1 Jan 2022 17:18:34 +0530 Subject: [Tutor] Appropriate use of None Message-ID: Dear Sir, Consider an example of reading a file, along with exception handling in the below given way: file = None try: file =open("filefortest.txt") text = file.read() except IOError: print("File can't be read") else: print(text) finally: if file != None: file.close() print("File is closed") Here I have assigned None to a variable file in the beginning. Then in try block the file object is assigned to the same variable file. This is done so to make the variable "file" available in finally block holding a value "None" when an exception is raised in the try block while reading the file. Kindly comment if this kind of practice should be done or not ? Regards Manprit Singh From alan.gauld at yahoo.co.uk Sat Jan 1 07:11:29 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 1 Jan 2022 12:11:29 +0000 Subject: [Tutor] Appropriate use of None In-Reply-To: References: Message-ID: On 01/01/2022 11:48, Manprit Singh wrote: > file = None > try: > file =open("filefortest.txt") > text = file.read() > except IOError: > print("File can't be read") > else: > print(text) > finally: > if file != None: > file.close() > print("File is closed") > > Kindly comment if this kind of practice should be done or not ? It should not be done because you should use "with" instead which will automatically close the file. try: with open(...) as infile: # process here except IOError: print("File filefortest.txt cannot be opened") else: print("File is closed") The more unnecessary tests you introduce the more potential for 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 mats at wichmann.us Sat Jan 1 12:43:46 2022 From: mats at wichmann.us (Mats Wichmann) Date: Sat, 1 Jan 2022 10:43:46 -0700 Subject: [Tutor] Appropriate use of None In-Reply-To: References: Message-ID: <47eaa9b8-768f-9346-8b07-c7be0fa58022@wichmann.us> On 1/1/22 04:48, Manprit Singh wrote: > Dear Sir, > > Consider an example of reading a file, along with exception handling in the > below given way: > > file = None > try: > file =open("filefortest.txt") > text = file.read() > except IOError: > print("File can't be read") > else: > print(text) > finally: > if file != None: > file.close() > print("File is closed") > > Here I have assigned None to a variable file in the beginning. Then in try > block > the file object is assigned to the same variable file. This is done so to > make the variable "file" available in finally block holding a value "None" > when an exception > is raised in the try block while reading the file. > > Kindly comment if this kind of practice should be done or not ? Alan has already replied well so I know I'm just piling on here. You're trying to handle two situations with this piece of code: 1. opening/reading a file, which might throw an error 2. making sure the file resource is cleaned up when you're done with it. For the latter, using a context manager is helpful because it shortens the "boilerplate" we otherwise have to write, which consists of: setup resource that needs cleanup try: work with resource finally: cleanup and now can become with resource that needs cleanup work with resource as long as a context manager has been defined for that resource - this would be a class that provides two special methods, __enter__ and __exit__, which are the "setup" and "cleanup" steps from the original. And such a context manager has indeed been provided in the standard Python language for file opening, so you can use the "with" statement happily here - and not need to use a sentinel. you still want a try block to handle possible errors opening the file, if you're being careful. Meanwhile, your None question: use of an out-of-band value as a sentinel to enable you to detect that some piece of code did not actually execute is in general fine, as long as you commit to actually doing that test - which you are doing, so that's good. In your piece of code it's pretty obvious, but many times it isn't - someone writes a function which returns some type of data, but can also return None if the data could not be determined. Then callers just go ahead and act on the returned data, not checking (maybe not knowing that they needed to, if documentation is incomplete or whatever reason) for None first. And then you get the dreaded error: AttributeError: 'NoneType' object has no attribute 'close' There was a recent article on this topic that you (and others?) might find interesting - I'll stop writing now and let this guy go into many more details.... https://engineeringblog.ridereport.com/pythons-none-problem From martin at linux-ip.net Sat Jan 1 12:32:03 2022 From: martin at linux-ip.net (Martin A. Brown) Date: Sat, 1 Jan 2022 09:32:03 -0800 Subject: [Tutor] Appropriate use of None In-Reply-To: References: Message-ID: Hello all, > It should not be done because you should use "with" instead > which will automatically close the file. I'll second this motion. > The more unnecessary tests you introduce the more potential > for error. And, I'll second that motion. > try: > with open(...) as infile: > # process here > except IOError: > print("File filefortest.txt cannot be opened") > else: > print("File is closed") > A person I worked with a decade ago used to say "my software inhabits a hostile universe" and when you have seen enough strange system configurations, errors, crashes and other failures, you can see why this mindset might prevail. With that in mind, I have two things I would add to Alan's skeleton suggestion, Manprit. send status messagse to STDERR ------------------------------ is to send the status-like messages to STDERR, keeping STDOUT for your expected output. Alternately, you could consider the logging module, but printing to STDERR is a perfectly normal technique. say what happened when catching an exception (and continuing) ------------------------------------------------------------- If you are catching an exception and continuing, mention what happened (unless you are correcting or deliberately swallowing the exception). There's on old theme, thta matches with Alan's comment above. "Don't catch any exception you're not prepared to handle." So, consider something like this. import sys def do_stuff_with(f): try: with open(f) as infile: pass except IOError as err: print("Skipping file {}: {}".format(f, err), file=sys.stderr) else: print("File {} is closed".format(f), file=sys.stderr) if __name__ == '__main__': for arg in sys.argv[1:]: do_stuff_with(arg) Where I have used "pass", you would put your processing logic, to call another function, collect data for return (this function doesn't return anything) or simply perform the desired work inline. When I run the above tiny program (which I called manprit-open-error.py) with 2 good input files and 3 different kinds of bad input files, I see the following produced to STDERR: $ cat manprit-open-error.py | python3 manprit-open-error.py /dev/stdin readable-file.txt /var/lib/ - unreadablefile File /dev/stdin is closed File readable-file.txt is closed Skipping file /var/lib/: [Errno 21] Is a directory: '/var/lib/' Skipping file -: [Errno 2] No such file or directory: '-' Skipping file unreadablefile: [Errno 13] Permission denied: 'unreadablefile' The above STDERR is useful for a user to understand what errors the program encountered while still letting your program try to succeed. -Martin P.S. Some programs accept "-" as a filename meaning STDIN. To my understanding that is something that is an application choice, which would require a bit of logic. I've added that as a creature comfort in some programs I have written, but not in the above toy example. -- Martin A. Brown http://linux-ip.net/ From finnjavier08 at gmail.com Sat Jan 1 13:23:19 2022 From: finnjavier08 at gmail.com (Finn Mason) Date: Sat, 1 Jan 2022 11:23:19 -0700 Subject: [Tutor] Appropriate use of None In-Reply-To: References: Message-ID: I'll second what everyone else has said. One note: You used `if file != None`. Since there is only ever one None object, it's considered best practice to test for identity with `file is not None` rather than for value (i.e. `file != None`). Hope that helps! -- Finn (Mobile) On Sat, Jan 1, 2022, 11:16 AM Martin A. Brown via Tutor wrote: > > Hello all, > > > It should not be done because you should use "with" instead > > which will automatically close the file. > > I'll second this motion. > > > The more unnecessary tests you introduce the more potential > > for error. > > And, I'll second that motion. > > > try: > > with open(...) as infile: > > # process here > > except IOError: > > print("File filefortest.txt cannot be opened") > > else: > > print("File is closed") > > > > A person I worked with a decade ago used to say "my software > inhabits a hostile universe" and when you have seen enough strange > system configurations, errors, crashes and other failures, you can > see why this mindset might prevail. > > With that in mind, I have two things I would add to Alan's skeleton > suggestion, Manprit. > > send status messagse to STDERR > ------------------------------ > is to send the status-like messages to STDERR, keeping STDOUT for > your expected output. Alternately, you could consider the logging > module, but printing to STDERR is a perfectly normal technique. > > say what happened when catching an exception (and continuing) > ------------------------------------------------------------- > If you are catching an exception and continuing, mention what > happened (unless you are correcting or deliberately swallowing the > exception). There's on old theme, thta matches with Alan's comment > above. "Don't catch any exception you're not prepared to handle." > > So, consider something like this. > > import sys > > > def do_stuff_with(f): > try: > with open(f) as infile: > pass > except IOError as err: > print("Skipping file {}: {}".format(f, err), file=sys.stderr) > else: > print("File {} is closed".format(f), file=sys.stderr) > > > if __name__ == '__main__': > for arg in sys.argv[1:]: > do_stuff_with(arg) > > > Where I have used "pass", you would put your processing logic, to > call another function, collect data for return (this function > doesn't return anything) or simply perform the desired work inline. > > When I run the above tiny program (which I called > manprit-open-error.py) with 2 good input files and 3 different kinds > of bad input files, I see the following produced to STDERR: > > $ cat manprit-open-error.py | python3 manprit-open-error.py /dev/stdin > readable-file.txt /var/lib/ - unreadablefile > File /dev/stdin is closed > File readable-file.txt is closed > Skipping file /var/lib/: [Errno 21] Is a directory: '/var/lib/' > Skipping file -: [Errno 2] No such file or directory: '-' > Skipping file unreadablefile: [Errno 13] Permission denied: > 'unreadablefile' > > The above STDERR is useful for a user to understand what errors the > program encountered while still letting your program try to succeed. > > -Martin > > P.S. Some programs accept "-" as a filename meaning STDIN. To my > understanding that is something that is an application choice, > which would require a bit of logic. I've added that as a creature > comfort in some programs I have written, but not in the above toy > example. > > -- > Martin A. Brown > http://linux-ip.net/ > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From jose.fonseca at external.stellantis.com Thu Jan 6 13:52:01 2022 From: jose.fonseca at external.stellantis.com (Jose Fonseca Garcia) Date: Thu, 6 Jan 2022 12:52:01 -0600 Subject: [Tutor] Modules on Python Message-ID: Hello, We like to know how to update Python Modules on many servers and then those modules to be used for applications. Thanks in advance Saludos/Regards Jos? Fonseca Garc?a Corporation Infrastructure (52 55) 50817361 From alan.gauld at yahoo.co.uk Thu Jan 6 19:32:44 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 7 Jan 2022 00:32:44 +0000 Subject: [Tutor] Modules on Python In-Reply-To: References: Message-ID: On 06/01/2022 18:52, Jose Fonseca Garcia via Tutor wrote: > Hello, > > We like to know how to update Python Modules on many servers and then those > modules to be used for applications. Which modules do you mean? Python comes with many modules as part of the standard install. You update them by updating Python. In addition there are thousands of third party modules available. You need to update them from the original source - often PyPi. PyPi modules can be managed using the pip tool. If you run Linux you may get them from your package manager. But you need to know which modules you have and want to update and to which version you need to update - it depends on the Python version you are running. The good news is that usually once you have updated the modules they will be available for the corresponding version of Python to use. -- 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 PyTutor at DancesWithMice.info Thu Jan 6 20:33:58 2022 From: PyTutor at DancesWithMice.info (dn) Date: Fri, 7 Jan 2022 14:33:58 +1300 Subject: [Tutor] Modules on Python In-Reply-To: References: Message-ID: <304274d1-e11d-41a2-997e-aa8402b8522f@DancesWithMice.info> On 07/01/2022 13.32, Alan Gauld via Tutor wrote: > On 06/01/2022 18:52, Jose Fonseca Garcia via Tutor wrote: >> Hello, >> >> We like to know how to update Python Modules on many servers and then those >> modules to be used for applications. > > Which modules do you mean? > > Python comes with many modules as part of the standard install. > You update them by updating Python. > > In addition there are thousands of third party modules available. > You need to update them from the original source - often PyPi. > PyPi modules can be managed using the pip tool. > > If you run Linux you may get them from your package manager. > But you need to know which modules you have and want to update > and to which version you need to update - it depends on the > Python version you are running. > > The good news is that usually once you have updated the modules > they will be available for the corresponding version of Python > to use. With a bit more information about the problem, more specific answers will become possible... If a professional operating system and network is in-use, there are tools which will implement each of these (or any of the above that may be relevant), on any number of servers, concurrently, and from a single command. -- Regards, =dn From diana.katz at gmail.com Fri Jan 7 10:10:38 2022 From: diana.katz at gmail.com (Diana Katz) Date: Fri, 7 Jan 2022 10:10:38 -0500 Subject: [Tutor] Fwd: blackline In-Reply-To: <2a40d35e981548ce84067f5e431e114b@selectequity.com> References: <2a40d35e981548ce84067f5e431e114b@selectequity.com> Message-ID: Hi, I need to figure out a way to use image recognition python code to go through hundreds of these backline filings and search for various key words in the GREEN text only - the additions. Is there a simple way to do this or code online I could work with? From alan.gauld at yahoo.co.uk Fri Jan 7 18:18:06 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 7 Jan 2022 23:18:06 +0000 Subject: [Tutor] Fwd: blackline In-Reply-To: References: <2a40d35e981548ce84067f5e431e114b@selectequity.com> Message-ID: On 07/01/2022 15:10, Diana Katz wrote: > Hi, > I need to figure out a way to use image recognition python code to go > through hundreds of these backline filings and search for various key words > in the GREEN text only - the additions. Is there a simple way to do this or > code online I could work with? The tutor list is for those learning the python language and its standard library. I don't think you'll find anything there that will help with this. You should probably try asking on both the main Python list and possibly the SciPy forum where other users with similar needs may be found. Details of the main list can be found here: http://mail.python.org/mailman/listinfo/python-list And the Scipy forum is at: https://mail.python.org/mailman/listinfo/scipy-user 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 mhysnm1964 at gmail.com Tue Jan 11 05:34:59 2022 From: mhysnm1964 at gmail.com (mhysnm1964 at gmail.com) Date: Tue, 11 Jan 2022 21:34:59 +1100 Subject: [Tutor] filename comparison Message-ID: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> All, Problem Description: I have over 8000 directories. In each directory there is a text file and a MP3 file. Below is the file naming structure for an MP3 or text file: Other Mother plot.txt Other Mother.mp3 What should occur: * Each directory should have both the above two files. * There can be multiple MP3 and text files in the same directory. * I want to find out which directories do not have a plot text file associated to the already existing mp3 file. * I want to find out which plot text file does not have a mp3 file. I have already managed to walk the directory structure using os.walk. But I am struggling with the best method of comparing the existing files. Anyone have any ideas how to approach this problem? As I am completely stuck on how to resolve this. Sean From PyTutor at DancesWithMice.info Tue Jan 11 06:08:44 2022 From: PyTutor at DancesWithMice.info (dn) Date: Wed, 12 Jan 2022 00:08:44 +1300 Subject: [Tutor] filename comparison In-Reply-To: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> References: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> Message-ID: <4fc9a804-06a7-e6d1-0b3a-ac6f5e034c8a@DancesWithMice.info> On 11/01/2022 23.34, mhysnm1964 at gmail.com wrote: > Problem Description: I have over 8000 directories. In each directory there > is a text file and a MP3 file. Below is the file naming structure for an MP3 > or text file: > > Other Mother plot.txt > Other Mother.mp3 > > What should occur: > > * Each directory should have both the above two files. > * There can be multiple MP3 and text files in the same directory. > * I want to find out which directories do not have a plot text file > associated to the already existing mp3 file. > * I want to find out which plot text file does not have a mp3 file. > > I have already managed to walk the directory structure using os.walk. But I > am struggling with the best method of comparing the existing files. > > Anyone have any ideas how to approach this problem? As I am completely stuck > on how to resolve this. Please review the (newer) pathlib library (https://docs.python.org/3/library/pathlib.html) and/or the (older) os.path library. Both enable manipulation of path and filenames - many of us code from memory using the latter, but these days it's probably better to start by learning the newer library! These will enable taking each filename and separating it into filename and extension/file-type (.txt or .mp3). This will facilitate checking that the files exist in appropriate pairs, by type. There are functions to see if one string startswith() or endswith() a sub-string (https://docs.python.org/3/library/stdtypes.html?text-sequence-type-str). These will facilitate relating "Other Mother plot" to "Other Mother". Recommendation: ignore the (already solved) directory structure side of things, and start by working with only a single directory containing the various permutations of multiple correct-pairs, and incorrect singletons. 1 How to decide that the filenames correspond? 2 how to check that the pair includes one .txt and one .mp3. 3 consider the error-conditions of non-matching pairs, and 4 'orphan files'. NB if the above is built as a function, then it should be an easy task to (once complete) fit it 'inside' the directory-walk already coded... If you'd like to ask a further question, please come back to us with the code you have so-far (copy-paste). -- Regards, =dn From __peter__ at web.de Tue Jan 11 06:11:11 2022 From: __peter__ at web.de (Peter Otten) Date: Tue, 11 Jan 2022 12:11:11 +0100 Subject: [Tutor] Break element into list while iterating In-Reply-To: References: Message-ID: <02f24924-d134-7ce1-8a46-24056807898f@web.de> On 25/12/2021 18:11, Julius Hamilton wrote: > Hey, > > I would like to do some kind of list comprehension where elements meeting > certain conditions get split on a delimiter. They don?t become lists nested > in one element in the previous list; the new elements just get inserted > where the old one was. > > Like this: > > [?apple?, ?pear?] > > -> > > [?a?, ?p?, ?p?, ?l?, ?e?, ?pear?] > > Is there a list comprehension syntax where if I split an element with > e.split(), I can ?insert? those elements at the element they came from? While you can solve this with a list comprehension... >>> [y for x in ["apple", "pear"] for y in (x if x == "apple" else [x])] ['a', 'p', 'p', 'l', 'e', 'pear'] I recommend a generator instead: >>> def explode_some(items, predicate, split): for item in items: if predicate(item): yield from split(item) else: yield item >>> >>> print(list( explode_some( ["apple", "pear"], lambda x: x == "apple", list ) )) ['a', 'p', 'p', 'l', 'e', 'pear'] You'd probably inline the predicate() and split() functions unless you need them to be configurable in your actual use case. From __peter__ at web.de Tue Jan 11 06:11:11 2022 From: __peter__ at web.de (Peter Otten) Date: Tue, 11 Jan 2022 12:11:11 +0100 Subject: [Tutor] Break element into list while iterating In-Reply-To: References: Message-ID: <02f24924-d134-7ce1-8a46-24056807898f@web.de> On 25/12/2021 18:11, Julius Hamilton wrote: > Hey, > > I would like to do some kind of list comprehension where elements meeting > certain conditions get split on a delimiter. They don?t become lists nested > in one element in the previous list; the new elements just get inserted > where the old one was. > > Like this: > > [?apple?, ?pear?] > > -> > > [?a?, ?p?, ?p?, ?l?, ?e?, ?pear?] > > Is there a list comprehension syntax where if I split an element with > e.split(), I can ?insert? those elements at the element they came from? While you can solve this with a list comprehension... >>> [y for x in ["apple", "pear"] for y in (x if x == "apple" else [x])] ['a', 'p', 'p', 'l', 'e', 'pear'] I recommend a generator instead: >>> def explode_some(items, predicate, split): for item in items: if predicate(item): yield from split(item) else: yield item >>> >>> print(list( explode_some( ["apple", "pear"], lambda x: x == "apple", list ) )) ['a', 'p', 'p', 'l', 'e', 'pear'] You'd probably inline the predicate() and split() functions unless you need them to be configurable in your actual use case. From learn2program at gmail.com Tue Jan 11 13:47:08 2022 From: learn2program at gmail.com (Alan Gauld) Date: Tue, 11 Jan 2022 18:47:08 +0000 Subject: [Tutor] filename comparison In-Reply-To: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> References: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> Message-ID: <2cf5d7f3-ec9b-7b85-e36e-5a07a431f80c@yahoo.co.uk> On 11/01/2022 10:34, mhysnm1964 at gmail.com wrote: > * Each directory should have both the above two files. > * There can be multiple MP3 and text files in the same directory. > * I want to find out which directories do not have a plot text file > associated to the already existing mp3 file. > * I want to find out which plot text file does not have a mp3 file. > Pseudo code: index = 0 files = sorted(filelist)?? # group the names together while files to process: ????? first = files[index] ????? if first is not mp3:????? # mp3 is missing ??????????? log error ??????????? index +=1 ???? elif files[index+1] is not txt???? # text file is missing ?????????? log other error ????????? index += 1 ???? else: index += 2????? a pair so step to next mp3 You could use? iterator next() functions instead of indices? but in this case I think the explicit index is clearer. > -- > 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 Jan 12 05:25:08 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 12 Jan 2022 11:25:08 +0100 Subject: [Tutor] filename comparison In-Reply-To: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> References: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> Message-ID: On 11/01/2022 11:34, mhysnm1964 at gmail.com wrote: > All, > > > > Problem Description: I have over 8000 directories. In each directory there > is a text file and a MP3 file. Below is the file naming structure for an MP3 > or text file: > > > > Other Mother plot.txt > > Other Mother.mp3 > > > > What should occur: > > * Each directory should have both the above two files. > * There can be multiple MP3 and text files in the same directory. > * I want to find out which directories do not have a plot text file > associated to the already existing mp3 file. > * I want to find out which plot text file does not have a mp3 file. > > > > I have already managed to walk the directory structure using os.walk. But I > am struggling with the best method of comparing the existing files. > > > > Anyone have any ideas how to approach this problem? As I am completely stuck > on how to resolve this. Given the filenames in one directory your task reduces to a few set operations on the names without their respective suffix: >>> files = ["foo.mp3", "bar.mp3", "bar plot.txt", "baz plot.txt"] Get the "stems" from the text files: >>> txt_only = {n[:-9] for n in files if n.endswith(" plot.txt")} >>> txt_only {'bar', 'baz'} The same for the audio files: >>> mp3_only = {n[:-4] for n in files if n.endswith(".mp3")} >>> mp3_only {'bar', 'foo'} Try turning the above into a function stems(files, suffix) that works for arbitrary suffixes. Now the beauty of this approach: getting the stems of the missing text files: >>> missing_txt = mp3_only - txt_only >>> missing_txt {'foo'} Swap the two sets to get the stems of the missing mp3 files. Before reporting you may want to add the suffixes: >>> {n + " plot.txt" for n in missing_txt} {'foo plot.txt'} PS: Getting the stems of the complete pairs is just as easy: >>> txt_only & mp3_only {'bar'} From __peter__ at web.de Wed Jan 12 05:25:08 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 12 Jan 2022 11:25:08 +0100 Subject: [Tutor] filename comparison In-Reply-To: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> References: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> Message-ID: On 11/01/2022 11:34, mhysnm1964 at gmail.com wrote: > All, > > > > Problem Description: I have over 8000 directories. In each directory there > is a text file and a MP3 file. Below is the file naming structure for an MP3 > or text file: > > > > Other Mother plot.txt > > Other Mother.mp3 > > > > What should occur: > > * Each directory should have both the above two files. > * There can be multiple MP3 and text files in the same directory. > * I want to find out which directories do not have a plot text file > associated to the already existing mp3 file. > * I want to find out which plot text file does not have a mp3 file. > > > > I have already managed to walk the directory structure using os.walk. But I > am struggling with the best method of comparing the existing files. > > > > Anyone have any ideas how to approach this problem? As I am completely stuck > on how to resolve this. Given the filenames in one directory your task reduces to a few set operations on the names without their respective suffix: >>> files = ["foo.mp3", "bar.mp3", "bar plot.txt", "baz plot.txt"] Get the "stems" from the text files: >>> txt_only = {n[:-9] for n in files if n.endswith(" plot.txt")} >>> txt_only {'bar', 'baz'} The same for the audio files: >>> mp3_only = {n[:-4] for n in files if n.endswith(".mp3")} >>> mp3_only {'bar', 'foo'} Try turning the above into a function stems(files, suffix) that works for arbitrary suffixes. Now the beauty of this approach: getting the stems of the missing text files: >>> missing_txt = mp3_only - txt_only >>> missing_txt {'foo'} Swap the two sets to get the stems of the missing mp3 files. Before reporting you may want to add the suffixes: >>> {n + " plot.txt" for n in missing_txt} {'foo plot.txt'} PS: Getting the stems of the complete pairs is just as easy: >>> txt_only & mp3_only {'bar'} From mhysnm1964 at gmail.com Wed Jan 12 05:45:01 2022 From: mhysnm1964 at gmail.com (mhysnm1964 at gmail.com) Date: Wed, 12 Jan 2022 21:45:01 +1100 Subject: [Tutor] filename comparison In-Reply-To: References: <019d01d806d6$e380b2a0$aa8217e0$@GMAIL.COM> Message-ID: <06e501d807a1$74da43e0$5e8ecba0$@GMAIL.COM> Peter and Alan, Thanks again for your support here. I have been playing with the Pseudo code Alan has provided. Got somewhere with it. But I am going to play with the below code as well. The end goal here is to build a database or spreadsheet with all my books containing information from Google books API. I have got this working to a 90% level. Just don't like how google books API returns results when you give it a filter of "full" based upon an author name or a book title. I don't want to see near matches. Only exact matches. I will have to play with the request get method string to get this right. I also have to work out how to inject "intitle" "inauthor" params into the string as well. The param function from requests doesn't seem to include it. Sean -----Original Message----- From: Tutor On Behalf Of Peter Otten Sent: Wednesday, 12 January 2022 9:25 PM To: tutor at python.org Subject: Re: [Tutor] filename comparison On 11/01/2022 11:34, mhysnm1964 at gmail.com wrote: > All, > > > > Problem Description: I have over 8000 directories. In each directory > there is a text file and a MP3 file. Below is the file naming > structure for an MP3 or text file: > > > > Other Mother plot.txt > > Other Mother.mp3 > > > > What should occur: > > * Each directory should have both the above two files. > * There can be multiple MP3 and text files in the same directory. > * I want to find out which directories do not have a plot text file > associated to the already existing mp3 file. > * I want to find out which plot text file does not have a mp3 file. > > > > I have already managed to walk the directory structure using os.walk. > But I am struggling with the best method of comparing the existing files. > > > > Anyone have any ideas how to approach this problem? As I am completely > stuck on how to resolve this. Given the filenames in one directory your task reduces to a few set operations on the names without their respective suffix: >>> files = ["foo.mp3", "bar.mp3", "bar plot.txt", "baz plot.txt"] Get the "stems" from the text files: >>> txt_only = {n[:-9] for n in files if n.endswith(" plot.txt")} >>> txt_only {'bar', 'baz'} The same for the audio files: >>> mp3_only = {n[:-4] for n in files if n.endswith(".mp3")} >>> mp3_only {'bar', 'foo'} Try turning the above into a function stems(files, suffix) that works for arbitrary suffixes. Now the beauty of this approach: getting the stems of the missing text files: >>> missing_txt = mp3_only - txt_only >>> missing_txt {'foo'} Swap the two sets to get the stems of the missing mp3 files. Before reporting you may want to add the suffixes: >>> {n + " plot.txt" for n in missing_txt} {'foo plot.txt'} PS: Getting the stems of the complete pairs is just as easy: >>> txt_only & mp3_only {'bar'} _______________________________________________ Tutor maillist - Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From maxandrj at gmail.com Thu Jan 13 08:28:38 2022 From: maxandrj at gmail.com (massimo andriolo) Date: Thu, 13 Jan 2022 14:28:38 +0100 Subject: [Tutor] download Message-ID: Hello, I have made the download PYcharm but when I run it it says configuration incorrect... What I should do? From mats at wichmann.us Thu Jan 13 13:39:13 2022 From: mats at wichmann.us (Mats Wichmann) Date: Thu, 13 Jan 2022 11:39:13 -0700 Subject: [Tutor] download In-Reply-To: References: Message-ID: On 1/13/22 06:28, massimo andriolo wrote: > Hello, > I have made the download PYcharm but when I run it it says configuration > incorrect... What I should do? That sure sounds like a question for a JetBrains forum dedicated to PyCharm... From wlfraed at ix.netcom.com Thu Jan 13 14:24:00 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 13 Jan 2022 14:24:00 -0500 Subject: [Tutor] download References: Message-ID: On Thu, 13 Jan 2022 14:28:38 +0100, massimo andriolo declaimed the following: >Hello, >I have made the download PYcharm but when I run it it says configuration >incorrect... What I should do? Problem description is not clear. Are you getting this message when trying to start PyCharm, or when attempting to run a script file that you've edited in some project? Which Python have you installed (PyCharm does not include a Python interpreter -- you have to configure such in order to have it run scripts files)? Did you install it before installing PyCharm (I think my install found the Python I have on my path, without having me manually select it). https://www.jetbrains.com/help/pycharm/installation-guide.html#toolbox {Caveat -- while I have PyCharm installed, for my uses on Windows, the ActiveState Python included a simple PythonWin, which is what I normally use as it starts quickly} -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From alan.gauld at yahoo.co.uk Thu Jan 13 19:33:41 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 14 Jan 2022 00:33:41 +0000 Subject: [Tutor] download In-Reply-To: References: Message-ID: On 13/01/2022 18:39, Mats Wichmann wrote: > On 1/13/22 06:28, massimo andriolo wrote: >> Hello, >> I have made the download PYcharm but when I run it it says configuration >> incorrect... What I should do? > > That sure sounds like a question for a JetBrains forum dedicated to > PyCharm... Like this perhaps? https://intellij-support.jetbrains.com/hc/en-us/community/topics/200379535-PyCharm -- 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 Jan 13 19:36:51 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 14 Jan 2022 00:36:51 +0000 Subject: [Tutor] Pythonwin was Re: download In-Reply-To: References: Message-ID: On 13/01/2022 19:24, Dennis Lee Bieber wrote: > {Caveat -- while I have PyCharm installed, for my uses on Windows, the > ActiveState Python included a simple PythonWin, which is what I normally > use as it starts quickly} > Do ActiveState still provide the pythonwin IDE? Last time I used ActiveState they had greatly reduced what they supplied and were moving to a more cloud based arrangement, so I kind of lost interest. But if they still provide pythonwin then I might try again because I liked it better than IDLE on Windows. -- 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 mhysnm1964 at gmail.com Fri Jan 14 00:59:08 2022 From: mhysnm1964 at gmail.com (mhysnm1964 at gmail.com) Date: Fri, 14 Jan 2022 16:59:08 +1100 Subject: [Tutor] string comparison modules Message-ID: <005401d8090b$d9b88b30$8d29a190$@GMAIL.COM> Hello All, The personal project I am working on has progress nicely with the help from this group. I have hit another snag. The project I am working on is navigating my book library which is broken up in a directory structure. author name and in each directory is the title of the book as a filename. When I do a google search via the requests API. I am getting a number of results back. The results I have limited to 3. The result JSON data construct has an field for title and author. I want to only grab the correct author and title JSON record. As there is slight differences between the author and title I have provided to google and what I have received back. I am wondering what is the easiest method of doing a string compare? For example: Returned from Google - Author: S. A. Smith I provided: S A Smith The title from google is: Russia in Revolution, An Empire in Crisis I sent: Russia in Revolution, An Empire in Crisis, 1890 to 1928 I could strip out the punctuation chars like '.'. I could use 'in' operator for the titles or the find method. AS there is so many different ways a title could be written or the author name. I am concern my approach is not very robust and I will not capture the right book record. I was going to compare the author and the title as part of the checking process. How should I proceed? Sean From alan.gauld at yahoo.co.uk Fri Jan 14 04:03:57 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 14 Jan 2022 09:03:57 +0000 Subject: [Tutor] string comparison modules In-Reply-To: <005401d8090b$d9b88b30$8d29a190$@GMAIL.COM> References: <005401d8090b$d9b88b30$8d29a190$@GMAIL.COM> Message-ID: On 14/01/2022 05:59, mhysnm1964 at gmail.com wrote: > result JSON data construct has an field for title and author. I want to only > grab the correct author and title JSON record. As there is slight > differences between the author and title I have provided to google and what > I have received back. I am wondering what is the easiest method of doing a > string compare? First you have to define what "correct" means. Is it an exact match? - apparently not. Does it mean a punctuationless match? - yes but also... Does it mean of a fixed length? - maybe but we don;t have enough samples Does it mean excluding numbers? - possibly we don;t have enough data Only you can answer those questions. (And more study of sample data) > Returned from Google - Author: S. A. Smith > I provided: S A Smith > > The title from google is: Russia in Revolution, An Empire in Crisis > I sent: Russia in Revolution, An Empire in Crisis, 1890 to 1928 > I could strip out the punctuation chars like '.'. That may well be a starting point > I could use 'in' operator I doubt if that is a good strategy. > for the titles or the find method. That might work, but will require some processing of the data first. > AS there is so many different ways a > title could be written or the author name. I am concern my approach is not > very robust and I will not capture the right book record. Only you can decide what you need. One loose search mechanism is to simply take the set of characters used and see if the search set is equal to(or a complete subset of) the returned result. Or vice versa. But that will potentially yield multiple results for a single search term. You need to decide if that is good enough, or if you need to narrow down to a single (or zero) result. Another approach is to use regular expressions. But that requires a very carefully defined query. In any case you need to sit down and think very carefully and specifically about what you define as a match. How flexible should it be. You haven't mentioned case, but does the case matter? Would "s a smith" count in the example above? -- 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 bouncingcats at gmail.com Fri Jan 14 04:27:25 2022 From: bouncingcats at gmail.com (David) Date: Fri, 14 Jan 2022 20:27:25 +1100 Subject: [Tutor] string comparison modules In-Reply-To: <005401d8090b$d9b88b30$8d29a190$@GMAIL.COM> References: <005401d8090b$d9b88b30$8d29a190$@GMAIL.COM> Message-ID: On Fri, 14 Jan 2022 at 17:00, wrote: > string compare? > How should I proceed? google.com or similar internet search engine with a few keywords eg "python string compare similar" would be a good place to start. From mats at wichmann.us Fri Jan 14 09:41:55 2022 From: mats at wichmann.us (Mats Wichmann) Date: Fri, 14 Jan 2022 07:41:55 -0700 Subject: [Tutor] string comparison modules In-Reply-To: References: <005401d8090b$d9b88b30$8d29a190$@GMAIL.COM> Message-ID: <37f9c03a-c664-39f3-f4f2-70ddd2ac146b@wichmann.us> On 1/14/22 02:27, David wrote: > On Fri, 14 Jan 2022 at 17:00, wrote: > >> string compare? > >> How should I proceed? > > google.com or similar internet search engine > with a few keywords > eg "python string compare similar" > would be a good place to start. To help with the search, include the word "fuzzy" - that's what this is, a comparison of language strings that are not equal in computer terms, but similar enough in human terms (long ago I had a professor at university who was a pioneer in this field of work - Lofti Zadeh). You don't need to go full AI for this, although the Python world is blessed with the excellent nltk module (Natural Language Toolkit), there are some simpler routes that should get you what you want. From wlfraed at ix.netcom.com Fri Jan 14 11:55:39 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Fri, 14 Jan 2022 11:55:39 -0500 Subject: [Tutor] Pythonwin was Re: download References: Message-ID: On Fri, 14 Jan 2022 00:36:51 +0000, Alan Gauld via Tutor declaimed the following: > >Do ActiveState still provide the pythonwin IDE? > I'm a few versions out of date (3.8) so I don't know what they've done. I grumbled enough when getting 3.8 required me to create a bloody login, after decades of the "free" version being a simple direct download. >Last time I used ActiveState they had greatly reduced what >they supplied and were moving to a more cloud based arrangement, >so I kind of lost interest. But if they still provide pythonwin >then I might try again because I liked it better than IDLE on >Windows. Since Pythonwin was tied to the win32 extensions package, it may be available separately... https://www.pythonpool.com/pythonwin/ (though it has moved from SourceForge) https://github.com/mhammond/pywin32 -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From jess.jones.unitedkingdom at protonmail.com Fri Jan 14 16:25:26 2022 From: jess.jones.unitedkingdom at protonmail.com (Jessica Jones) Date: Fri, 14 Jan 2022 21:25:26 +0000 Subject: [Tutor] python update Message-ID: hi i have installed python in windows. I see there are many updates all the time Can my python update itself or do i have to uinstall it, download it, reinstall it each time again? Sent with [ProtonMail](https://protonmail.com/) Secure Email. From alan.gauld at yahoo.co.uk Fri Jan 14 20:17:06 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 15 Jan 2022 01:17:06 +0000 Subject: [Tutor] python update In-Reply-To: References: Message-ID: On 14/01/2022 21:25, Jessica Jones via Tutor wrote: > i have installed python in windows. I see there are many updates all the time > Can my python update itself or do i have to uinstall it, download it, reinstall it each time again? Don't sweat about updates, they are not usually needed unless you have a specific issue that's addressed. I'm still running 3.8 on one computer and 3.6 on another. I might upgrade after the next major release but maybe not. Most releases feature fairly esoteric features that most users don't need (and in many cases don't even understand!). Look at the release notes and if its not a major security issue or something you think you will use then you can ignore it. (Or just ignore everything but major releases and even then wait till the 2nd or 3rd iteration - let somebody else find the bugs!) When I worked in corporate IT we had an official policy of never upgrading anything till it was at least 2 major versions behind the bleeding edge. Stable is better than feature rich! -- 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 eryksun at gmail.com Fri Jan 14 21:59:52 2022 From: eryksun at gmail.com (Eryk Sun) Date: Fri, 14 Jan 2022 20:59:52 -0600 Subject: [Tutor] python update In-Reply-To: References: Message-ID: On 1/14/22, Alan Gauld via Tutor wrote: > > I'm still running 3.8 on one computer and 3.6 on another. I might > upgrade after the next major release but maybe not. Technically speaking, Python's version scheme is major.minor.micro. For example, for 3.11.0: >>> sys.version_info.major 3 >>> sys.version_info.minor 11 >>> sys.version_info.micro 0 In practice, 3.x is usually referred to as a "major" (i.e. significant) version of the language. Anyway, a 'minor' update (e.g. updating the micro version from 3.10.1 to 3.10.2) usually gets released every 3-4 months. This is an in-place upgrade, assuming it's the same build architecture (e.g. x86 or x86-64), so it's usually painless. However, unless it's an urgently needed bug fix or security fix, your life will be simpler if you wait a few weeks before upgrading, or hold off until it's really necessary. A minor update might mistakenly introduce bugs or new behavior, in which case a new update might have to be released ahead of schedule to correct the problem(s). The lifetime of a 'major' release is about 5 years, but installers are only made available for a couple years. For example, 3.6.0 was released on 2016-12-23, and the last update was 3.6.15 on 2021-09-04. However, the last version released with an installer was 3.6.8 on 2018-12-24. Versions 3.6.9 to 3.6.15 were source only releases, in which case for Windows you would need to build your own installer. (It's not hard to build the installer if you have the required version of Visual Studio and some experience building software.) From mats at wichmann.us Sat Jan 15 10:14:40 2022 From: mats at wichmann.us (Mats Wichmann) Date: Sat, 15 Jan 2022 08:14:40 -0700 Subject: [Tutor] python update In-Reply-To: References: Message-ID: <58e176c5-6d3f-8340-2ebf-8daafa369b6d@wichmann.us> On 1/14/22 14:25, Jessica Jones via Tutor wrote: > hi > > i have installed python in windows. I see there are many updates all the time > Can my python update itself or do i have to uinstall it, download it, reinstall it each time again? The python.org version will do micro updates in place (e.g. 3.10.1 to 3.10.2) - that is, you don't have to uninstall first. But you do need to initiate the download and install. The Microsoft Store version of Python updates the same way as the other store apps do - through the store client app. For both, you do have to manually initiate a new minor version (that is, going from 3.10 to 3.11). This is because such versions are designed to be able to coexist (I have a test system with all of 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, and 3.11-alpha installed for backwards-compatibility testing. 3.5 and 3.6 are end-of-life now so I'll probably get rid of those next time I'm doing some cleanup there). You can also install Python other ways - chocolatey.org is another approach. For that one, choco can tell you when apps are out of date, and you can install new versions through it. New minor versions happen only once a year. Micro versions are roughly every 2-3 months, depending on whether an important problem accelerates the cadence. From eryksun at gmail.com Sat Jan 15 12:01:40 2022 From: eryksun at gmail.com (Eryk Sun) Date: Sat, 15 Jan 2022 11:01:40 -0600 Subject: [Tutor] python update In-Reply-To: <58e176c5-6d3f-8340-2ebf-8daafa369b6d@wichmann.us> References: <58e176c5-6d3f-8340-2ebf-8daafa369b6d@wichmann.us> Message-ID: On 1/15/22, Mats Wichmann wrote: > > New minor versions happen only once a year. Micro versions are roughly > every 2-3 months, depending on whether an important problem accelerates > the cadence. While the version number of a release is major.minor.micro, 3.x is commonly referred to as a "major" version of Python 3. See PEP 602 -- Annual Release Cycle for Python: https://www.python.org/dev/peps/pep-0602 From leamhall at gmail.com Mon Jan 17 09:00:30 2022 From: leamhall at gmail.com (Leam Hall) Date: Mon, 17 Jan 2022 08:00:30 -0600 Subject: [Tutor] How to update only set CLI args? Message-ID: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Writing a CLI app in Python 3.10. There's a "defaults" dict, a config file that gets read into a dict, and command line arguments that can be passed in. defaults = {'table':'people'} defaults.update(config) defaults.update(vars(args)) The issue is that if an argument is not set on the command line, the args.item has a value of "None", which then overwrites any value in defaults or config. How do I update just the set args? Thanks! Leam -- Site Automation Programmer (reuel.net/resume) Scribe: The Domici War (domiciwar.net) General Ne'er-do-well (github.com/LeamHall) From alan.gauld at yahoo.co.uk Mon Jan 17 09:18:14 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 17 Jan 2022 14:18:14 +0000 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: On 17/01/2022 14:00, Leam Hall wrote: > Writing a CLI app in Python 3.10. There's a "defaults" dict, a config file that gets read into a dict, and command line arguments that can be passed in. > > defaults = {'table':'people'} > defaults.update(config) > defaults.update(vars(args)) > > The issue is that if an argument is not set on the command line, > the args.item has a value of "None", which then overwrites any value > in defaults or config. How do I update just the set args? Write a loop to test for none values before updating? -- 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 leamhall at gmail.com Mon Jan 17 09:23:01 2022 From: leamhall at gmail.com (Leam Hall) Date: Mon, 17 Jan 2022 08:23:01 -0600 Subject: [Tutor] How to update only set CLI args? In-Reply-To: References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: <79adc919-56b3-9741-55b2-3a6790b810e6@gmail.com> On 1/17/22 08:18, Alan Gauld via Tutor wrote: > On 17/01/2022 14:00, Leam Hall wrote: >> Writing a CLI app in Python 3.10. There's a "defaults" dict, a config file that gets read into a dict, and command line arguments that can be passed in. >> >> defaults = {'table':'people'} >> defaults.update(config) >> defaults.update(vars(args)) >> >> The issue is that if an argument is not set on the command line, >> the args.item has a value of "None", which then overwrites any value >> in defaults or config. How do I update just the set args? > > Write a loop to test for none values before updating? That I can do; I just thought there might be a cleaner way. Thanks! Leam -- Site Automation Programmer (reuel.net/resume) Scribe: The Domici War (domiciwar.net) General Ne'er-do-well (github.com/LeamHall) From __peter__ at web.de Mon Jan 17 10:00:06 2022 From: __peter__ at web.de (Peter Otten) Date: Mon, 17 Jan 2022 16:00:06 +0100 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: On 17/01/2022 15:00, Leam Hall wrote: > Writing a CLI app in Python 3.10. There's a "defaults" dict, a config > file that gets read into a dict, and command line arguments that can be > passed in. > > ? defaults = {'table':'people'} > ? defaults.update(config) > ? defaults.update(vars(args)) > > The issue is that if an argument is not set on the command line, the > args.item has a value of "None", which then overwrites any value in > defaults or config. How do I update just the set args? Do you process command line arguments with argparse? Then you might pass a custom namespace filled with your defaults: import argparse parser = argparse.ArgumentParser() parser.add_argument("--table") parser.add_argument("--extra") defaults = dict(table="people") ns = argparse.Namespace() vars(ns).update(defaults) print(parser.parse_args(namespace=ns)) From __peter__ at web.de Mon Jan 17 10:00:06 2022 From: __peter__ at web.de (Peter Otten) Date: Mon, 17 Jan 2022 16:00:06 +0100 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: On 17/01/2022 15:00, Leam Hall wrote: > Writing a CLI app in Python 3.10. There's a "defaults" dict, a config > file that gets read into a dict, and command line arguments that can be > passed in. > > ? defaults = {'table':'people'} > ? defaults.update(config) > ? defaults.update(vars(args)) > > The issue is that if an argument is not set on the command line, the > args.item has a value of "None", which then overwrites any value in > defaults or config. How do I update just the set args? Do you process command line arguments with argparse? Then you might pass a custom namespace filled with your defaults: import argparse parser = argparse.ArgumentParser() parser.add_argument("--table") parser.add_argument("--extra") defaults = dict(table="people") ns = argparse.Namespace() vars(ns).update(defaults) print(parser.parse_args(namespace=ns)) From cs at cskk.id.au Mon Jan 17 16:18:23 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 18 Jan 2022 08:18:23 +1100 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <79adc919-56b3-9741-55b2-3a6790b810e6@gmail.com> References: <79adc919-56b3-9741-55b2-3a6790b810e6@gmail.com> Message-ID: On 17Jan2022 08:23, Leam Hall wrote: >On 1/17/22 08:18, Alan Gauld via Tutor wrote: >>On 17/01/2022 14:00, Leam Hall wrote: >>>Writing a CLI app in Python 3.10. There's a "defaults" dict, a config file that gets read into a dict, and command line arguments that can be passed in. >>> >>> defaults = {'table':'people'} >>> defaults.update(config) >>> defaults.update(vars(args)) >>> >>>The issue is that if an argument is not set on the command line, >>>the args.item has a value of "None", which then overwrites any value >>>in defaults or config. How do I update just the set args? >> >>Write a loop to test for none values before updating? > >That I can do; I just thought there might be a cleaner way. Well you could filter() the args.items(). Not sure it is more readable. Cheers, Cameron Simpson From alexkleider at gmail.com Mon Jan 17 17:36:36 2022 From: alexkleider at gmail.com (Alex Kleider) Date: Mon, 17 Jan 2022 14:36:36 -0800 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: Have you considered/looked at docopt? >>> python3 -m pip install docopt On Mon, Jan 17, 2022 at 6:02 AM Leam Hall wrote: > Writing a CLI app in Python 3.10. There's a "defaults" dict, a config file > that gets read into a dict, and command line arguments that can be passed > in. > > defaults = {'table':'people'} > defaults.update(config) > defaults.update(vars(args)) > > The issue is that if an argument is not set on the command line, the > args.item has a value of "None", which then overwrites any value in > defaults or config. How do I update just the set args? > > Thanks! > > Leam > -- > Site Automation Programmer (reuel.net/resume) > Scribe: The Domici War (domiciwar.net) > General Ne'er-do-well (github.com/LeamHall) > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From leamhall at gmail.com Mon Jan 17 18:11:46 2022 From: leamhall at gmail.com (Leam Hall) Date: Mon, 17 Jan 2022 17:11:46 -0600 Subject: [Tutor] How to update only set CLI args? In-Reply-To: References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: On 1/17/22 08:18, Alan Gauld via Tutor wrote: > On 17/01/2022 14:00, Leam Hall wrote: >> Writing a CLI app in Python 3.10. There's a "defaults" dict, a config file that gets read into a dict, and command line arguments that can be passed in. >> >> defaults = {'table':'people'} >> defaults.update(config) >> defaults.update(vars(args)) >> >> The issue is that if an argument is not set on the command line, >> the args.item has a value of "None", which then overwrites any value >> in defaults or config. How do I update just the set args? > > Write a loop to test for none values before updating? > This is what I came up with, after my work day was done. :) ### def sort_args(defaults, config, args): """ Returns dict of configuration, with defaults lowest priority, then config file options, then CLI args as highest. """ defaults = copy.deepcopy(defaults) defaults.update(config) for key, value in vars(args).items(): if value: defaults[key] = value return defaults ### Back to testing. Leam -- Site Automation Programmer (reuel.net/resume) Scribe: The Domici War (domiciwar.net) General Ne'er-do-well (github.com/LeamHall) From PyTutor at DancesWithMice.info Mon Jan 17 18:32:23 2022 From: PyTutor at DancesWithMice.info (dn) Date: Tue, 18 Jan 2022 12:32:23 +1300 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <79adc919-56b3-9741-55b2-3a6790b810e6@gmail.com> References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> <79adc919-56b3-9741-55b2-3a6790b810e6@gmail.com> Message-ID: <63c72fcb-6c5c-2fa7-4f3c-d5b042e31c05@DancesWithMice.info> On 18/01/2022 03.23, Leam Hall wrote: > On 1/17/22 08:18, Alan Gauld via Tutor wrote: >> On 17/01/2022 14:00, Leam Hall wrote: >>> Writing a CLI app in Python 3.10. There's a "defaults" dict, a config >>> file that gets read into a dict, and command line arguments that can >>> be passed in. >>> >>> ??? defaults = {'table':'people'} >>> ??? defaults.update(config) >>> ??? defaults.update(vars(args)) >>> >>> The issue is that if an argument is not set on the command line, >>> the args.item has a value of "None", which then overwrites any value >>> in defaults or config. How do I update just the set args? >> >> Write a loop to test for none values before updating? > > That I can do; I just thought there might be a cleaner way. +1 @Alan's suggestion plus the more specific need to check *all* input *before* using it to direct action. Per your request for a "cleaner way" to merge dicts, Python 3.9+ offers the dict-union operator (https://docs.python.org/3/whatsnew/3.9.html) As you have noted, the order in which the dicts are employed is important, eg >>> d1 = { "a":1, "c":2, "d": 'Some', } >>> d2 = { "a":3, "b":4, "d":None } >>> d1 | d2 {'a': 3, 'c': 2, 'd': None, 'b': 4} but >>> d2 | d1 {'a': 1, 'b': 4, 'd': 'Some', 'c': 2} For your reading pleasure: "Python Merge Dictionaries ? Combine Dictionaries (7 Ways)" (https://datagy.io/python-merge-dictionaries/) -- Regards, =dn From PyTutor at DancesWithMice.info Mon Jan 17 18:39:44 2022 From: PyTutor at DancesWithMice.info (dn) Date: Tue, 18 Jan 2022 12:39:44 +1300 Subject: [Tutor] How to update only set CLI args? In-Reply-To: References: <1571f984-3c30-6692-3b72-d5c7bc909cc3@gmail.com> Message-ID: <9a12efae-610d-4fa0-afdb-f31d50d6e12f@DancesWithMice.info> On 18/01/2022 12.11, Leam Hall wrote: > On 1/17/22 08:18, Alan Gauld via Tutor wrote: >> On 17/01/2022 14:00, Leam Hall wrote: >>> Writing a CLI app in Python 3.10. There's a "defaults" dict, a config >>> file that gets read into a dict, and command line arguments that can >>> be passed in. >>> >>> ??? defaults = {'table':'people'} >>> ??? defaults.update(config) >>> ??? defaults.update(vars(args)) >>> >>> The issue is that if an argument is not set on the command line, >>> the args.item has a value of "None", which then overwrites any value >>> in defaults or config. How do I update just the set args? >> >> Write a loop to test for none values before updating? >> > > This is what I came up with, after my work day was done.? :) > > ### > > def sort_args(defaults, config, args): > ? """ Returns dict of configuration, with defaults lowest priority, > ????? then config file options, then CLI args as highest. > ? """ > ? defaults = copy.deepcopy(defaults) > ? defaults.update(config) > ? for key, value in vars(args).items(): > ??? if value: > ????? defaults[key] = value > ? return defaults > > ### > > Back to testing. If you already know the range of keys (as in this case), they could be put into a list (which may also be useful in other ways during the set-up and accumulation of the config vars). Then the code could loop through the list to build a combined dict. However, "Danger, Will Robinson": if each config-dict doesn't contain every key (in said list) - presumably with a value of None. If that is the case, (I think) a try-except would be 'cheaper' than sorting... (not that the size/speed is likely to be a real concern) -- Regards, =dn From cs at cskk.id.au Mon Jan 17 20:19:09 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 18 Jan 2022 12:19:09 +1100 Subject: [Tutor] How to update only set CLI args? In-Reply-To: References: Message-ID: On 17Jan2022 17:11, Leam Hall wrote: >This is what I came up with, after my work day was done. :) > >### > >def sort_args(defaults, config, args): > """ Returns dict of configuration, with defaults lowest priority, > then config file options, then CLI args as highest. > """ > defaults = copy.deepcopy(defaults) > defaults.update(config) > for key, value in vars(args).items(): > if value: This won't do the right thing if value is eg 0. If you know an omitted CLI option will be None (ideally it would not even be present) then do a precise check for None, not "falsiness". if value is not None: Cheers, Cameron Simpson From leamhall at gmail.com Mon Jan 17 21:17:54 2022 From: leamhall at gmail.com (Leam Hall) Date: Mon, 17 Jan 2022 20:17:54 -0600 Subject: [Tutor] How to update only set CLI args? In-Reply-To: References: Message-ID: <797e4469-dc67-9fe8-86f2-71e63f36ba2f@gmail.com> On 1/17/22 19:19, Cameron Simpson wrote: > On 17Jan2022 17:11, Leam Hall wrote: >> This is what I came up with, after my work day was done. :) >> >> ### >> >> def sort_args(defaults, config, args): >> """ Returns dict of configuration, with defaults lowest priority, >> then config file options, then CLI args as highest. >> """ >> defaults = copy.deepcopy(defaults) >> defaults.update(config) >> for key, value in vars(args).items(): >> if value: > > This won't do the right thing if value is eg 0. If you know an omitted > CLI option will be None (ideally it would not even be present) then do a > precise check for None, not "falsiness". > > if value is not None: > > Cheers, > Cameron Simpson That was my goal, but I didn't have the syntax. I had tried: if value not None: Code updated, thanks! Leam -- Site Automation Programmer (reuel.net/resume) Scribe: The Domici War (domiciwar.net) General Ne'er-do-well (github.com/LeamHall) From cs at cskk.id.au Tue Jan 18 03:28:39 2022 From: cs at cskk.id.au (Cameron Simpson) Date: Tue, 18 Jan 2022 19:28:39 +1100 Subject: [Tutor] How to update only set CLI args? In-Reply-To: <797e4469-dc67-9fe8-86f2-71e63f36ba2f@gmail.com> References: <797e4469-dc67-9fe8-86f2-71e63f36ba2f@gmail.com> Message-ID: On 17Jan2022 20:17, Leam Hall wrote: >On 1/17/22 19:19, Cameron Simpson wrote: >> if value is not None: > >That was my goal, but I didn't have the syntax. I had tried: > > if value not None: > >Code updated, thanks! None is a singleton, so you really want an object identity check, thus "is" (am I looking at this specific object?). Or of course "is not". Cheers, Cameron Simpson From phillor9 at gmail.com Wed Jan 19 01:20:50 2022 From: phillor9 at gmail.com (Phil) Date: Wed, 19 Jan 2022 17:20:50 +1100 Subject: [Tutor] a list of tuples with varying lengths Message-ID: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> I hope the following makes sense to you and I'm not sure that I should even post such a vague question. What I need is s, d to = (0, 4) during the first time interval and then s, d = (0, 3) and (1, 4) the second time. There are many time intervals, this is just the first two. My solution is to have a look_up table that looks something like this, the first three entries are: table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] The first entry has 1 tuple the second entry has 2 tuples the third has 3 tuples, etc My first thought was to extract the tuple values with a for-loop with a variable range, like this: for s, d in range(len(table[index])) but that idea ended in failure. I cannot see a simple way to calculate the values even though there is a pattern and so a look-up table seems like a good idea. I've spent days on this and have made little progress so any ideas will be greatly appreciated. -- Regards, Phil From roel at roelschroeven.net Wed Jan 19 03:45:44 2022 From: roel at roelschroeven.net (Roel Schroeven) Date: Wed, 19 Jan 2022 09:45:44 +0100 Subject: [Tutor] a list of tuples with varying lengths In-Reply-To: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> Message-ID: <1862f11d-311d-5ca3-850a-f2e80cb4660e@roelschroeven.net> Op 19/01/2022 om 7:20 schreef Phil: > I hope the following makes sense to you and I'm not sure that I should > even post such a vague question. > > What I need is s, d to = (0, 4) during the first time interval and > then s, d = (0, 3) and (1, 4) the second time. There are many time > intervals, this is just the first two. > > My solution is to have a look_up table that looks something like this, > the first three entries are: > > table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] > > The first entry has 1 tuple the second entry has 2 tuples the third > has 3 tuples, etc > > My first thought was to extract the tuple values with a for-loop with > a variable range, like this: for s, d in range(len(table[index])) but > that idea ended in failure. I cannot see a simple way to calculate the > values even though there is a pattern and so a look-up table seems > like a good idea. > > I've spent days on this and have made little progress so any ideas > will be greatly appreciated. Something like this? lookup_table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] for time_interval in lookup_table: ??? print('{} tuple(s) in this time interval:'.format(len(time_interval))) ??? for s, d in time_interval: ??????? print('??? {}, {}'.format(s, d)) That outputs this: 1 tuple(s) in this time interval: ??? 0, 4 2 tuple(s) in this time interval: ??? 0, 3 ??? 1, 4 3 tuple(s) in this time interval: ??? 0, 2 ??? 1, 3 ??? 2, 4 In cases where you don't only need each element but also want a loop index, use enumerate(): lookup_table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] for time_interval_index, time_interval in enumerate(lookup_table): ??? print('{} tuple(s) in time interval {}:'.format(len(time_interval), time_interval_index)) ??? for i, (s, d) in enumerate(time_interval): ??????? print('??? {}: {}, {}'.format(i, s, d)) This variation outputs: 1 tuple(s) in time interval 0: ??? 0: 0, 4 2 tuple(s) in time interval 1: ??? 0: 0, 3 ??? 1: 1, 4 3 tuple(s) in time interval 2: ??? 0: 0, 2 ??? 1: 1, 3 ??? 2: 2, 4 -- "Je ne suis pas d?accord avec ce que vous dites, mais je me battrai jusqu?? la mort pour que vous ayez le droit de le dire." -- Attribu? ? Voltaire "I disapprove of what you say, but I will defend to the death your right to say it." -- Attributed to Voltaire "Ik ben het niet eens met wat je zegt, maar ik zal je recht om het te zeggen tot de dood toe verdedigen" -- Toegeschreven aan Voltaire From __peter__ at web.de Wed Jan 19 04:10:46 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 19 Jan 2022 10:10:46 +0100 Subject: [Tutor] a list of tuples with varying lengths In-Reply-To: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> Message-ID: On 19/01/2022 07:20, Phil wrote: > I hope the following makes sense to you and I'm not sure that I should > even post such a vague question. > > What I need is s, d to = (0, 4) during the first time interval and then > s, d = (0, 3) and (1, 4) the second time. There are many time intervals, > this is just the first two. > > My solution is to have a look_up table that looks something like this, > the first three entries are: > > table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] That's not a list of tuples -- it's a list of lists of tuples. To iterate over the tuples you need two nested loops: >>> table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] >>> for row in table: for field in row: print(field) (0, 4) (0, 3) (1, 4) (0, 2) (1, 3) (2, 4) As all tuples have a length of two you can safely unpack them in the inner loop: >>> for row in table: for s, d in row: print(f"{s=}, {d=}") s=0, d=4 s=0, d=3 s=1, d=4 s=0, d=2 s=1, d=3 s=2, d=4 By the way, the table you give doesn't look like a "lookup table" which is typically used to provide a "key" (the list index in your case) and return a "value" (here a complete row). But you seem to want the individual tuples, and all of them. Perhaps you'd like to explain the problem you are trying solve? Some of us might be willing clear things up a bit for you ;) > The first entry has 1 tuple the second entry has 2 tuples the third has > 3 tuples, etc > > My first thought was to extract the tuple values with a for-loop with a > variable range, like this: for s, d in range(len(table[index])) but that > idea ended in failure. I cannot see a simple way to calculate the values > even though there is a pattern and so a look-up table seems like a good > idea. > > I've spent days on this and have made little progress so any ideas will > be greatly appreciated. > From __peter__ at web.de Wed Jan 19 04:10:46 2022 From: __peter__ at web.de (Peter Otten) Date: Wed, 19 Jan 2022 10:10:46 +0100 Subject: [Tutor] a list of tuples with varying lengths In-Reply-To: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> Message-ID: On 19/01/2022 07:20, Phil wrote: > I hope the following makes sense to you and I'm not sure that I should > even post such a vague question. > > What I need is s, d to = (0, 4) during the first time interval and then > s, d = (0, 3) and (1, 4) the second time. There are many time intervals, > this is just the first two. > > My solution is to have a look_up table that looks something like this, > the first three entries are: > > table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] That's not a list of tuples -- it's a list of lists of tuples. To iterate over the tuples you need two nested loops: >>> table = [[(0, 4)], [(0, 3), (1, 4)], [(0, 2), (1, 3), (2, 4)]] >>> for row in table: for field in row: print(field) (0, 4) (0, 3) (1, 4) (0, 2) (1, 3) (2, 4) As all tuples have a length of two you can safely unpack them in the inner loop: >>> for row in table: for s, d in row: print(f"{s=}, {d=}") s=0, d=4 s=0, d=3 s=1, d=4 s=0, d=2 s=1, d=3 s=2, d=4 By the way, the table you give doesn't look like a "lookup table" which is typically used to provide a "key" (the list index in your case) and return a "value" (here a complete row). But you seem to want the individual tuples, and all of them. Perhaps you'd like to explain the problem you are trying solve? Some of us might be willing clear things up a bit for you ;) > The first entry has 1 tuple the second entry has 2 tuples the third has > 3 tuples, etc > > My first thought was to extract the tuple values with a for-loop with a > variable range, like this: for s, d in range(len(table[index])) but that > idea ended in failure. I cannot see a simple way to calculate the values > even though there is a pattern and so a look-up table seems like a good > idea. > > I've spent days on this and have made little progress so any ideas will > be greatly appreciated. > From phillor9 at gmail.com Thu Jan 20 01:28:00 2022 From: phillor9 at gmail.com (Phil) Date: Thu, 20 Jan 2022 17:28:00 +1100 Subject: [Tutor] a list of tuples with varying lengths In-Reply-To: References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> Message-ID: <0d5ccba1-0e08-a310-7a7b-4eeab0ab8607@gmail.com> On 19/1/22 20:10, Peter Otten wrote: > Thank you Roel and Peter, I think the main problem was that I needed a break to give myself a chance to think more clearly. My stubborn use of "for i in range(len(x))" instead of "for i in x" has once again led me down the wrong path. This is the key to the solution: for row in table: ????for s, d in row: > By the way, the table you give doesn't look like a "lookup table" which > is typically used to provide a "key" (the list index in your case) and > return a "value" (here a complete row). But you seem to want the > individual tuples, and all of them. I stand corrected again and extracting the individual tuples was the crux of the problem. I use lookup tables frequently. A second lookup table in this project uses a letter of the alphabet to return the letter's hex values. > > Perhaps you'd like to explain the problem you are trying solve? > Some of us might be willing clear things up a bit for you ;) OK, it's quite likely that there's a far better plan of attack to solve this problem. I'm simulating an 8 x 8 Led matrix. The function that's not working correctly is scrolling text and this is how I'm trying to get it going. I'm using a 5 x 7 font and the letter, for example, 'P' is stored like this: self.letter_table = ["0x7f", "0x09", "0x09", "0x09", "0x06"] A function converts this to a byte list, so 'P' now looks like this: [ ? 1111000, ? 1000100, ? 1000100, ? 1111000, ? 1000000, ? 1000000, ? 1000000 ] Now this is where the 's' and 'd' comes in, 's' is the source (byte list) and 'd' is the destination (the led matrix). So the first column of the byte list is stored on the last column (the right hand side) of the led matrix during the first time interval. During the second time interval, the same column of the byte list is stored on the second last column of the led matrix and the second column of the byte table is stored on the last column of the led matrix. This continues until the entire letter is displayed on the led matrix. Each slice of the letter is shifted across the led matrix in 5 time intervals. The simple solution is to copy the letter slice to the led matrix and then directly shift the displayed slice to the left one place before adding the second slice but that's not how physical led displays work. Data is written to the display but it cannot be read back. What I'm trying to create, in effect, is a led matrix driver and the only function, so far, that doesn't work correctly is scrolling text. I can see that my solution would only work for one 8 x 8 display and the complicated source destination table would become even more complex if I added more displays. Another thought that I experimented with was to create a virtual window of leds that I could move across the byte list but that became even more complex. Any thoughts on a less convoluted solution are most welcome. -- Regards, Phil From wlfraed at ix.netcom.com Thu Jan 20 15:30:50 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 20 Jan 2022 15:30:50 -0500 Subject: [Tutor] a list of tuples with varying lengths References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> <0d5ccba1-0e08-a310-7a7b-4eeab0ab8607@gmail.com> Message-ID: On Thu, 20 Jan 2022 17:28:00 +1100, Phil declaimed the following: >I'm simulating an 8 x 8 Led matrix. The function that's not working >correctly is scrolling text and this is how I'm trying to get it going. > Don't know if actual LED code may be of use (some of them incorporate shift registers). https://learn.adafruit.com/connecting-a-16x32-rgb-led-matrix-panel-to-a-raspberry-pi/overview >The simple solution is to copy the letter slice to the led matrix and >then directly shift the displayed slice to the left one place before >adding the second slice but that's not how physical led displays work. >Data is written to the display but it cannot be read back. > To my mind, the "simple solution" is similar to the linked Adafruit article... PREBUILD the entire display string as a bitmap first. Then feed it to the "simulated" display in a loop, wherein the end of each loop cycle shifts the bitmap. Include enough empty columns to allow for blank screen at start/end of the main loop. If each data item in the bitmap is one column (I'm not going to the level of a physical "bitmap" image structure, just a list of column data) in the display, scrolling is just a matter of each pass starting on a different location (and use modulo to wrap at the end). Pseudo-code (I'm not going to take the time to actually build a working version) #build bitmap including initial blanks # bitmap = [ 0x00, #8 times for blank display # 0xnn, #as needed for text data ] offset = 0 while True: #obviously you'll want some way to interrupt/update for col in range(8): #assume 8 column display writeDisplay(col, bitmap[(col+offset) % 8]) offset += 1 OR, if writeDisplay() expects all 8x8 values while True: writeDisplay(bitmap[offset % 8 : (offset + 8) % 8]) offset += 1 One exit could be offset > len(bitmap) so you could produce the next bitmap string to display (hmmm, could be a point for threading -- one thread gets the bitmap from a Queue and runs the above loop, and end of bitmap it fetches next Queue bitmap. Main thread reads whatever source of text and converts to bitmap lists). Reset offset to 0 on entry... -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From wlfraed at ix.netcom.com Thu Jan 20 15:37:02 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 20 Jan 2022 15:37:02 -0500 Subject: [Tutor] a list of tuples with varying lengths References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> <0d5ccba1-0e08-a310-7a7b-4eeab0ab8607@gmail.com> Message-ID: On Thu, 20 Jan 2022 15:30:50 -0500, Dennis Lee Bieber declaimed the following: >OR, if writeDisplay() expects all 8x8 values > >while True: > writeDisplay(bitmap[offset % 8 : (offset + 8) % 8]) Whoops... that should be % len(bitmap) and not % 8 (both places) -- might be a similar flaw in the explicit column loop version -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Thu Jan 20 19:42:53 2022 From: phillor9 at gmail.com (Phil) Date: Fri, 21 Jan 2022 11:42:53 +1100 Subject: [Tutor] a list of tuples with varying lengths In-Reply-To: References: <1ff634e9-bfcb-7d5e-ff4f-4ac099d5c38f@gmail.com> <0d5ccba1-0e08-a310-7a7b-4eeab0ab8607@gmail.com> Message-ID: <1f047dff-35ea-e2b8-b3cd-81e51d1095ec@gmail.com> On 21/1/22 07:30, Dennis Lee Bieber wrote: > On Thu, 20 Jan 2022 17:28:00 +1100, Phil declaimed the > following: Thank you Dennis for your thoughts, you may have diverted me from the circular path that I've been following. > Don't know if actual LED code may be of use (some of them incorporate > shift registers). My current project started by simulating a shift register and a string of simulated LEDs 18 months ago. An 8 x 8 LED matrix seemed like an interesting idea. > https://learn.adafruit.com/connecting-a-16x32-rgb-led-matrix-panel-to-a-raspberry-pi/overview These projects usually use a MAX7219 IC together with an imported driver and it's this driver that I'm attempting to build. I'll have a look, this one may be different. > PREBUILD the entire display string as a bitmap first. Then feed it to > the "simulated" display in a loop, wherein the end of each loop cycle > shifts the bitmap. That's what I've done except I'm using a list of bytes (the equivalent of a C byte array). I think extracting columns from .png file, for example, would add an extra level of difficulty. Anyway, you've given me an idea. I should be able to adapt my simulated shift register code to shift an entire column of data across the simulated LED matrix display. 7 one bit shift registers maybe? -- Regards, Phil From mhysnm1964 at gmail.com Sat Jan 22 23:09:13 2022 From: mhysnm1964 at gmail.com (mhysnm1964 at gmail.com) Date: Sun, 23 Jan 2022 15:09:13 +1100 Subject: [Tutor] adding new keys to a nested dict Message-ID: <002701d8100e$fcb11580$f6134080$@GMAIL.COM> Hello all I am trying to add new keys to a dict and finding the previous key is being overridden. Below is the structure: newScore {'Bar 1': { 'Time signature': "text", 'tempo': 'tempo', 'beat 1': { 'voice 1': {} }, }, } As you can tell by the code below. I am starting with an empty dict. In the code I am dynamically creating the nested dict. I am finding when I add the time signature key under the 'bar 1' dict node. It is being overridden, rather than adding a new key. Not sure why this is occurring. I can add nested dicts with one key value. I want to be able to insert a new key and keep the existing keys in that dict node as outline. newScore = {} bar = '' # stores the current bar being worked upon. beat = '' # stores the current beat being worked upon. voice = '' # stores the current voice being worked upon. for notation in score: if notation[0] == 'Barline Single barline': notation.pop(0) # remove the matched pattern. for word in notation: if word.startswith('Bar'): if word not in newScore: bar = word newScore[bar] = {} elif word.startswith('Beat'): if word not in newScore[bar]: beat = word voice = 'Voice 1' newScore[bar][beat] = { voice: []} #else: #newScore[bar][beat][voice].append(word) elif notation[0].startswith('Vertical Frame'): if 'Vertical Frame' not in newScore: newScore['Vertical Frame'] = notation elif notation[0].startswith('Time Signature'): # include time signature regardless if it is the same under the right beat and voice. #print (notation) newScore[bar] = {'Time Signature': notation[0]} # newScore[bar]['Time Signature'] = notation[0] # syntax error elif notation[0].startswith('Treble clef'): #print (notation) newScore[bar]['clef'] =notation[0] elif notation[0].startswith('Rest '): print (notation) for i in range(0, len(notation)): if notation[i] == beat: notation.pop(i) # remove the word beat value. # newScore[bar][beat][voice].append(notation) I keep getting syntax errors or the 'beat' and other keys within the 'bar 1' are removed only leaving the last dict key. It only occurs in the nested dict. What am I doing wrong. From mhysnm1964 at gmail.com Sat Jan 22 23:36:20 2022 From: mhysnm1964 at gmail.com (mhysnm1964 at gmail.com) Date: Sun, 23 Jan 2022 15:36:20 +1100 Subject: [Tutor] adding new keys to a nested dict In-Reply-To: <002701d8100e$fcb11580$f6134080$@GMAIL.COM> References: <002701d8100e$fcb11580$f6134080$@GMAIL.COM> Message-ID: <00c201d81012$c6680070$53380150$@GMAIL.COM> All, Resolved the issue. The end code I used was: newScore[bar]['Time Signature'] = notation[0] I am sure I used the above before. Anyway, issue fixed. From: mhysnm1964 at gmail.com Sent: Sunday, 23 January 2022 3:09 PM To: tutor at python.org Subject: adding new keys to a nested dict Hello all I am trying to add new keys to a dict and finding the previous key is being overridden. Below is the structure: newScore {'Bar 1': { 'Time signature': "text", 'tempo': 'tempo', 'beat 1': { 'voice 1': {} }, }, } As you can tell by the code below. I am starting with an empty dict. In the code I am dynamically creating the nested dict. I am finding when I add the time signature key under the 'bar 1' dict node. It is being overridden, rather than adding a new key. Not sure why this is occurring. I can add nested dicts with one key value. I want to be able to insert a new key and keep the existing keys in that dict node as outline. newScore = {} bar = '' # stores the current bar being worked upon. beat = '' # stores the current beat being worked upon. voice = '' # stores the current voice being worked upon. for notation in score: if notation[0] == 'Barline Single barline': notation.pop(0) # remove the matched pattern. for word in notation: if word.startswith('Bar'): if word not in newScore: bar = word newScore[bar] = {} elif word.startswith('Beat'): if word not in newScore[bar]: beat = word voice = 'Voice 1' newScore[bar][beat] = { voice: []} #else: #newScore[bar][beat][voice].append(word) elif notation[0].startswith('Vertical Frame'): if 'Vertical Frame' not in newScore: newScore['Vertical Frame'] = notation elif notation[0].startswith('Time Signature'): # include time signature regardless if it is the same under the right beat and voice. #print (notation) newScore[bar] = {'Time Signature': notation[0]} # newScore[bar]['Time Signature'] = notation[0] # syntax error elif notation[0].startswith('Treble clef'): #print (notation) newScore[bar]['clef'] =notation[0] elif notation[0].startswith('Rest '): print (notation) for i in range(0, len(notation)): if notation[i] == beat: notation.pop(i) # remove the word beat value. # newScore[bar][beat][voice].append(notation) I keep getting syntax errors or the 'beat' and other keys within the 'bar 1' are removed only leaving the last dict key. It only occurs in the nested dict. What am I doing wrong. From okeyerinne at gmail.com Wed Jan 26 17:17:31 2022 From: okeyerinne at gmail.com (Okechukwu Erinne) Date: Wed, 26 Jan 2022 16:17:31 -0600 Subject: [Tutor] Question related to Python Message-ID: Hello there, I was just going to ask how to write a program to create an output similar to the one attached to this email (with the line numbers included). Thank you, Oke. From alan.gauld at yahoo.co.uk Thu Jan 27 11:02:04 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 27 Jan 2022 16:02:04 +0000 Subject: [Tutor] Question related to Python In-Reply-To: References: Message-ID: On 26/01/2022 22:17, Okechukwu Erinne wrote: > I was just going to ask how to write a program to create an output similar > to the one attached to this email (with the line numbers included). The list is text only so if you attached a screen shot or similar it will have been stripped by the server for security. Please cut n paste the text into the email body. Also just showing the output is not going to help unless you want a program consisting of a series of hard coded print statements. A description of the problem, input and output( this is your display part) is needed. Ideally, show us the code you have already written (we won't do it for you!) and we can help steer you in the right direction. Also show us any error messages(in full) and tell us the OS and Python version. It all helps narrow things down. -- 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 m at hvdev.cc Thu Jan 27 08:28:52 2022 From: m at hvdev.cc (=?UTF-8?Q?V=C5=A9_Thanh_H=E1=BA=A3i?=) Date: Thu, 27 Jan 2022 20:28:52 +0700 Subject: [Tutor] Question related to Python In-Reply-To: References: Message-ID: <17e9bb9806e.5f00f1f130705.9101447927306633176@hvdev.cc> Hello Oke, I think the attachment is missing. Or maybe I can't access it because it was dropped by the mailing list system. Kind regards, Vu Thanh Hai Full-stack Developer -o-0_o-0-o_0-o-0_o-0-o- ? Website: www.hvdev.cc Email: m at hvdev.cc Twitter: @hvhvdevdev GitHub: @hvhvdevdev ---- On Thu, 27 Jan 2022 05:17:31 +0700 Okechukwu Erinne wrote ---- > Hello there, > > I was just going to ask how to write a program to create an output similar > to the one attached to this email (with the line numbers included). > > Thank you, > Oke. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From chris.gass.177 at gmail.com Thu Jan 27 18:08:28 2022 From: chris.gass.177 at gmail.com (Christopher Gass) Date: Thu, 27 Jan 2022 15:08:28 -0800 Subject: [Tutor] Iterate Through a Dictionary where the Values are Tuples Message-ID: Hello, I'm working on a project to write a script that will do some basic unit recommendations for a fire department while their usual computer system is offline. Right now it's a proof of concept, so it's not built out fully. As part of this script, I'm attempting to iterate over a dictionary where the values are tuples. More specifically, the keys are the unit numbers for the fire apparatus and the values are a tuple containing the unit type (Engine, Aid Car, etc.) and assigned station. I'm calling the tuple containing the unit type and station assignment "details" and I'm trying to then iterate through that tuple to see if the unit type and station assignment match what's being requested in the response plan. When I try to iterate through "details" however, I'm receiving a "too many values to unpack" error. Do you have a solution to this error or maybe another way I could approach the problem? Thanks for the help. position = { 'TAC_1':['BA0001', 'BA0002', 'BA0003', 'BA0004'], 'TAC_7':['DF009', 'DF010', 'DF011', 'DF013', 'DF055'] } TAC_1 = { 'BLS':[['Aid Unit', 'Engine', 'Ladder']], 'BLSN':[['Aid Unit', 'Engine', 'Ladder']], 'MED':['Medic Unit', 'Engine'], 'MEDX':['Medic Unit', ['Engine', 'Ladder'], ['Engine', 'Ladder'], 'Medical Services Officer'] } station_order = { 'BA0001':['STA 2', 'STA 3', 'STA 1', 'STA 5', 'STA 4', 'STA 6', 'STA 7', 'STA 61', 'STA 63', 'STA 82'], 'BA0002':['STA 2', 'STA 3', 'STA 1', 'STA 5', 'STA 4', 'STA 6', 'STA 7', 'STA 61', 'STA 63', 'STA 82'] } units = { 'A2':('Aid Unit', 'STA 2'), 'E2':('Engine', 'STA 2'), } def recommendations(call_type,grid): call_type = call_type.strip().upper() grid = grid.strip().upper() result = [] apparatus = [] i = 0 unit_details = () radio_position = get_radio(grid) if radio_position == 'TAC_1': radio_position = TAC_1 response_plan = radio_position[call_type] rec_station_order = station_order[grid] for unit_type in response_plan: for x in unit_type: for station in rec_station_order: for unit, details in units.items(): for u_type, unit_station in details: if u_type == unit_type and unit_station == station and unit not in result: result.append(unit) apparatus.append(response_plan[i]) i += 1 return result print(recommendations('bls','BA0001')) -Christopher Gass chris.gass.177 at gmail.com From learn2program at gmail.com Thu Jan 27 19:10:11 2022 From: learn2program at gmail.com (Alan Gauld) Date: Fri, 28 Jan 2022 00:10:11 +0000 Subject: [Tutor] Iterate Through a Dictionary where the Values are Tuples In-Reply-To: References: Message-ID: <13e79b7a-29fe-ffa6-8243-863fb216dce5@yahoo.co.uk> On 27/01/2022 23:08, Christopher Gass wrote: > what's being requested in the response plan. When I try to > iterate through "details" however, I'm receiving a "too many values to > unpack" error. Please, always include the full error traceback. It contains a lot of detail that can help diagnose the problem. Especially in a very complex bit of code like this where multiple aliases and several interlinked data structures are being used.? (BTW Have you considered converting this to a database? It looks to me like SQL might be a better fit! SQLite is ideal for this kind of project.) Another option might be an OOP approach, most of those dictionaries represent objects and you could move a lot of the code into methods, thus avoiding the explicitly heavy nesting of loops. (They will still be nested, but hidden inside method calls) It should be more readable if nothing else! > units = { > 'A2':('Aid Unit', 'STA 2'), > 'E2':('Engine', 'STA 2'), > } > > def recommendations(call_type,grid): > call_type = call_type.strip().upper() > grid = grid.strip().upper() > result = [] > apparatus = [] > i = 0 > unit_details = () > radio_position = get_radio(grid) > if radio_position == 'TAC_1': > radio_position = TAC_1 > response_plan = radio_position[call_type] > rec_station_order = station_order[grid] > for unit_type in response_plan: > for x in unit_type: > for station in rec_station_order: I assume this next bit is where the error occurs? > for unit, details in units.items(): > for u_type, unit_station in details: And the above line specifically? It looks like it should work. That's why I'd like to see what exactly python is complaining about in the error message. -- 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 wlfraed at ix.netcom.com Thu Jan 27 19:49:17 2022 From: wlfraed at ix.netcom.com (Dennis Lee Bieber) Date: Thu, 27 Jan 2022 19:49:17 -0500 Subject: [Tutor] Iterate Through a Dictionary where the Values are Tuples References: Message-ID: <15b6vg98ocsst5cko7m8fpb17h4sbmb62o@4ax.com> On Thu, 27 Jan 2022 15:08:28 -0800, Christopher Gass declaimed the following: >what's being requested in the response plan. When I try to >iterate through "details" however, I'm receiving a "too many values to >unpack" error. Do you have a solution to this error or maybe another way I >could approach the problem? Thanks for the help. >position = { > 'TAC_1':['BA0001', 'BA0002', 'BA0003', 'BA0004'], > 'TAC_7':['DF009', 'DF010', 'DF011', 'DF013', 'DF055'] >} Is it guaranteed that the items in the lists are singular? (That is, "BA0002" will only appear once is the entire structure?) > >TAC_1 = { > 'BLS':[['Aid Unit', 'Engine', 'Ladder']], > 'BLSN':[['Aid Unit', 'Engine', 'Ladder']], > 'MED':['Medic Unit', 'Engine'], > 'MEDX':['Medic Unit', ['Engine', 'Ladder'], ['Engine', 'Ladder'], 'Medical >Services Officer'] >} > >station_order = { > 'BA0001':['STA 2', 'STA 3', 'STA 1', 'STA 5', 'STA 4', 'STA 6', 'STA 7', >'STA 61', 'STA 63', 'STA 82'], > 'BA0002':['STA 2', 'STA 3', 'STA 1', 'STA 5', 'STA 4', 'STA 6', 'STA 7', >'STA 61', 'STA 63', 'STA 82'] >} > >units = { > 'A2':('Aid Unit', 'STA 2'), > 'E2':('Engine', 'STA 2'), >} > >def recommendations(call_type,grid): > call_type = call_type.strip().upper() > grid = grid.strip().upper() > result = [] > apparatus = [] > i = 0 > unit_details = () > radio_position = get_radio(grid) Since you didn't provide get_radio() I'm having to infer that it is doing a reverse lookup -- that is, it is looking for "grid" in the list of values, and then returning the KEY for "position". > if radio_position == 'TAC_1': > radio_position = TAC_1 If you have to expand this all keys in "position" it is going to get confusing... Ignoring that get_radio() is returning a string which is bound to radio_position... and then you replace that binding with another dictionary. > response_plan = radio_position[call_type] > rec_station_order = station_order[grid] > for unit_type in response_plan: > for x in unit_type: You don't seem to be doing anything with "x" > for station in rec_station_order: > for unit, details in units.items(): > for u_type, unit_station in details: Details, at this point, is (example) ("Aid Unit", "STA 2") so iterating returns "Aid Unit" as the first item which you are trying to unpack into two values -- as a string, it unpacks into characters. Try tuple unpacking u_type, unit_station = details > if u_type == unit_type and unit_station == station >and unit not in result: Seems rather confusing... The top loop is pulling unit_type, the second loop does something with it, and down here you are comparing back to the top unit... You don't really seem to be doing much with all those dictionaries > result.append(unit) > apparatus.append(response_plan[i]) > i += 1 > return result Why are you accumulating "apparatus" but not returning it? > >print(recommendations('bls','BA0001')) Does this get closer to what you intended? Note the inversion of some of your dictionaries. -=-=- TAC_1 = { "BLS" : [ ["Aid Unit", "Engine", "Ladder"] ], "BLSN" : [ ["Aid Unit", "Engine", "Ladder"] ], "MED" : [ ["Medic Unit"], ["Engine"] ], "MEDX" : [ ["Medic Unit"], ["Engine", "Ladder"], ["Engine", "Ladder"], ["Medical Services Officer"] ] } TAC_7 = { "TBD" : ["TBD"] } position = { "BA0001" : TAC_1, "BA0002" : TAC_1, "BA0003" : TAC_1, "BA0004" : TAC_1, "DF009" : TAC_7, "DF010" : TAC_7, "DF011" : TAC_7, "DF013" : TAC_7, "DF055" : TAC_7 } station_order = { "BA0001" : [ "STA 2", "STA 3", "STA 1", "STA 5", "STA 4", "STA 6", "STA 7", "STA 61", "STA 63", "STA 82" ], "BA0002" : [ "STA 2", "STA 3", "STA 1", "STA 5", "STA 4", "STA 6", "STA 7", "STA 61", "STA 63", "STA 82" ] } units = { ("Aid Unit", "STA 2") : "A2", ("Engine", "STA 2") : "E2" } def recommendation(call_type, grid): call_type = call_type.strip().upper() grid = grid.strip().upper() result = [] apparatus = [] # ensure items exist if (position.get(grid, None) is None or station_order.get(grid, None) is None): return "GRID %s is not valid" % grid if position[grid].get(call_type, None) is None: return "GRID/CALL_TYPE %s/%s is not valid" % (grid, call_type) # response plan loop for response_units in position[grid][call_type]: for ru in response_units: # station loop for station in station_order[grid]: unit = units.get( (ru, station), None) if unit is not None: result.append(unit) apparatus.append(ru) return (result, apparatus) print(recommendation("bls", "ba0001") ) -=-=- -- Wulfraed Dennis Lee Bieber AF6VN wlfraed at ix.netcom.com http://wlfraed.microdiversity.freeddns.org/ From phillor9 at gmail.com Fri Jan 28 00:35:33 2022 From: phillor9 at gmail.com (Phil) Date: Fri, 28 Jan 2022 16:35:33 +1100 Subject: [Tutor] Alphabet lookup table Message-ID: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> I have a 5 x 7 font lookup table class method that returns five hex values for a character. So far I've only created six entries and being basically lazy I'm wondering if something like this has already been created, failing that, is this the correct way to go about it anyway? An Internet search didn't reveal such a module. class Alphabet: ??? def __init__(self): ??????? self.alpha_table = {'P': ['0x7f', '0x09', '0x09', '0x09', '0x06'], ?????????????????????????? ?? ??? ???? 'H': ['0x7f', '0x08', '0x08', '0x08', '0x7f'], ??????????????????????????? ??? ??? ?? 'I': ['0x00', '0x41', '0x7f', '0x41', '0x00'], ??????????????????????????? ??? ??? ?? 'L': ['0x7f', '0x40', '0x40', '0x40', '0x40'], ??????????????????????????? ??? ??? ?? '.': ['0x00', '0x60', '0x60', '0x00', '0x00'], ??????????????????????????? ??? ??? ?? ' ': ['0x00', '0x00', '0x00', '0x00', '0x00'] ??????????????????????????? ??? ??? ? } ??? def get_char(self, char): ??????? return self.alpha_table[char] -- Regards, Phil From alan.gauld at yahoo.co.uk Fri Jan 28 02:51:40 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 28 Jan 2022 07:51:40 +0000 Subject: [Tutor] Alphabet lookup table In-Reply-To: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> References: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> Message-ID: On 28/01/2022 05:35, Phil wrote: > I have a 5 x 7 font lookup table class method that returns five hex > values for a character. So far I've only created six entries and being > basically lazy I'm wondering if something like this has already been > created, failing that, is this the correct way to go about it anyway? > Assuming this is still part of your LED simulation then yes, this is a fairly common approach. You might find it easier to use binary rather than hex though. And I'd put the letter definitions into a separate module - that way it's easy to change "fonts" by renaming the files. alpha_table = { 'P' : ['0b01111111', '0b00001001', '0b00001001', '0b00001001', '0b00000110'], 'H' : ['0b01111111', '0b00000100', '0b00000100', '0b00000100', '0b01111111'], I : [ etc... > An Internet search didn't reveal such a module. > > class Alphabet: > ??? def __init__(self): > ??????? self.alpha_table = {'P': ['0x7f', '0x09', '0x09', '0x09', '0x06'], > ?????????????????????????? ?? ??? ???? 'H': ['0x7f', '0x08', '0x08', > '0x08', '0x7f'], > ??????????????????????????? ??? ??? ?? 'I': ['0x00', '0x41', '0x7f', > '0x41', '0x00'], ??????????????????????? ??? ??? ? } > > ??? def get_char(self, char): > ??????? return self.alpha_table[char] > -- 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 phillor9 at gmail.com Fri Jan 28 04:02:26 2022 From: phillor9 at gmail.com (Phil) Date: Fri, 28 Jan 2022 20:02:26 +1100 Subject: [Tutor] Alphabet lookup table In-Reply-To: References: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> Message-ID: <6b40f1a1-4800-cd48-5f2a-161c34670d63@gmail.com> On 28/1/22 18:51, Alan Gauld via Tutor wrote: > > Assuming this is still part of your LED simulation then yes, > this is a fairly common approach. Thank Alan for your reply and yes this is part of my LED simulation which is working well. The text to be scrolled is entered by the user, me, into a text control and off it goes. > You might find it easier > to use binary rather than hex though. I thought about that. The LED scroller includes a function that converts the hex value to a byte array so it's probably an unnecessary step. > And I'd put the letter > definitions into a separate module - that way it's easy to > change "fonts" by renaming the files. > > > alpha_table = { > 'P' : ['0b01111111', > '0b00001001', > '0b00001001', > '0b00001001', > '0b00000110'], Do you mean a listing like this, rather than a class with only one method that I already have? -- Regards, Phil From alan.gauld at yahoo.co.uk Fri Jan 28 05:00:11 2022 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 28 Jan 2022 10:00:11 +0000 Subject: [Tutor] Alphabet lookup table In-Reply-To: <6b40f1a1-4800-cd48-5f2a-161c34670d63@gmail.com> References: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> <6b40f1a1-4800-cd48-5f2a-161c34670d63@gmail.com> Message-ID: On 28/01/2022 09:02, Phil wrote: >> You might find it easier >> to use binary rather than hex though. > I thought about that. The LED scroller includes a function that converts > the hex value to a byte array so it's probably an unnecessary step. The representation of the literal strings has no relevance to the conversion to bytes, only how it looks on screen. The binary representation makes it easier to see which pixels are on/off and thus easier to debug. Although, with this representation you do have to tilt your head sideways to see it! :-) But thinking about this you don't even need to use strings, just use the numbers: P = [0b01111111, 0b00001001, 0b00001001, 0b00001001, 0b00000110] You could then use the struct module to convert to bytes: p_bytes = struct.pack('hhhhh',P) That might be easier? Just a thought. >> definitions into a separate module - that way it's easy to >> change "fonts" by renaming the files. >> >> >> alpha_table = { >> 'P' : ['0b01111111', >> '0b00001001', >> '0b00001001', >> '0b00001001', >> '0b00000110'], > > Do you mean a listing like this, rather than a class with only one > method that I already have? NO. Just put the dicts or class(es) into a separate file from the code that uses them. Thus you can just rename the module that defines the font you want to use to active.font or whatever. Your code then reads active.font to activate the LED. Thus you can easily have a range f different fonts and allow the user (or programmer) to select the currently active one. BTW A class with only one method is a code smell. It means you don't really need a class, you only need a data structure and a function. -- 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 phillor9 at gmail.com Fri Jan 28 19:44:42 2022 From: phillor9 at gmail.com (Phil) Date: Sat, 29 Jan 2022 11:44:42 +1100 Subject: [Tutor] Alphabet lookup table In-Reply-To: References: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> <6b40f1a1-4800-cd48-5f2a-161c34670d63@gmail.com> Message-ID: <111d6526-a890-caf7-46b0-423926c08a22@gmail.com> On 28/1/22 21:00, Alan Gauld via Tutor wrote: > > BTW A class with only one method is a code smell. It means you > don't really need a class, you only need a data structure and > a function. Your reply, Alan, initially caused me some confusion. My initial thought was along the lines of c struct but Python only has classes and not structures, as far as I know. However, after a night's sleep I now see what you mean. Is this what you had in mind? import alphabet print(alphabet.alpha_table['P']) alphabet.py contains just the dictionary lookup table. -- Regards, Phil From learn2program at gmail.com Fri Jan 28 20:09:58 2022 From: learn2program at gmail.com (Alan Gauld) Date: Sat, 29 Jan 2022 01:09:58 +0000 Subject: [Tutor] Alphabet lookup table In-Reply-To: <111d6526-a890-caf7-46b0-423926c08a22@gmail.com> References: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> <6b40f1a1-4800-cd48-5f2a-161c34670d63@gmail.com> <111d6526-a890-caf7-46b0-423926c08a22@gmail.com> Message-ID: On 29/01/2022 00:44, Phil wrote: > On 28/1/22 21:00, Alan Gauld via Tutor wrote: >> BTW A class with only one method is a code smell. It means you >> don't really need a class, you only need a data structure and >> a function. > > what you mean. Is this what you had in mind? > > import alphabet > > print(alphabet.alpha_table['P']) > > alphabet.py contains just the dictionary lookup table. Yes, or you could add a single function: alphabet.print_letter(letter) So: from alphabet import print_letter print_letter('P') So the single method becomes a function in the module. You still have information hiding and a function interface but no need for a class or instances. -- 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 phillor9 at gmail.com Fri Jan 28 23:53:27 2022 From: phillor9 at gmail.com (Phil) Date: Sat, 29 Jan 2022 15:53:27 +1100 Subject: [Tutor] Alphabet lookup table In-Reply-To: References: <9b627376-d920-2351-a2d0-42b78769ec23@gmail.com> <6b40f1a1-4800-cd48-5f2a-161c34670d63@gmail.com> <111d6526-a890-caf7-46b0-423926c08a22@gmail.com> Message-ID: <48120bda-790a-8dea-442f-ef47e1d8b5b9@gmail.com> On 29/1/22 12:09, Alan Gauld wrote: > > So the single method becomes a function in the module. You still have > information hiding and a function interface but no need for a class or > instances. And that's what I have now, thank you Alan. -- Regards, Phil From nathan-tech at hotmail.com Sat Jan 29 20:34:56 2022 From: nathan-tech at hotmail.com (Nathan Smith) Date: Sun, 30 Jan 2022 01:34:56 +0000 Subject: [Tutor] pass a memory pointer to a c function Message-ID: Hi list, Put simply, I have a c function which takes a memory pointer as one of the arguments, "An unmanaged pointer to the memory location as an IntPtr." which I am calling from a python program. I've done some digging and it looks like tempfile can write to the memory, but can I use that to then get the pointer and pass it over? More digging seems to indicate id(obj) gets the memory location for that object, but as it is a python object I'm guessing that is not much use? What I want the function to receive is the memory pointer for the data in the tempfile, rather than the python tempfile object. I've also figured out that ctypes.pointer(i) is probably what I want, where i is a ctypes.c_int(python_int) of some kind, but getting py_int to be the correct memory locations is my stumbling block Sorry in advance if my terms are off here, I'm only a passing c user and. I hope someone can point me in the right direction! Nathan -- Best Wishes, Nathan Smith, BSC My Website: https://nathantech.net From nathan-tech at hotmail.com Sat Jan 29 21:35:35 2022 From: nathan-tech at hotmail.com (Nathan Smith) Date: Sun, 30 Jan 2022 02:35:35 +0000 Subject: [Tutor] pass a memory pointer to a c function In-Reply-To: References: Message-ID: Hello! I actually managed to figure this out myself, but do have a related question (I hope you all don't mind!). My solution was: import ctypes data=b/"some text" x=bytearray(data) Buffer = ctypes.c_char * len(x) buf = Buffer.from_buffer(x) addr=ctypes.addressof(buf) Then pass addr to the c function. My question is, do I need to free that buffer? Will python do it when the object is deleted? Thanks On 30/01/2022 01:34, Nathan Smith wrote: > Hi list, > > > Put simply, I have a c function which takes a memory pointer as one of > the arguments, "An unmanaged pointer to the memory location as an > IntPtr." which I am calling from a python program. > > > I've done some digging and it looks like tempfile can write to the > memory, but can I use that to then get the pointer and pass it over? > > More digging seems to indicate id(obj) gets the memory location for > that object, but as it is a python object I'm guessing that is not > much use? > > What I want the function to receive is the memory pointer for the data > in the tempfile, rather than the python tempfile object. > > > I've also figured out that ctypes.pointer(i) is probably what I want, > where i is a ctypes.c_int(python_int) of some kind, but getting py_int > to be the correct memory locations is my stumbling block > > > Sorry in advance if my terms are off here, I'm only a passing c user and. > > I hope someone can point me in the right direction! > > Nathan > -- Best Wishes, Nathan Smith, BSC My Website: https://nathantech.net From eryksun at gmail.com Sun Jan 30 00:15:37 2022 From: eryksun at gmail.com (Eryk Sun) Date: Sat, 29 Jan 2022 23:15:37 -0600 Subject: [Tutor] pass a memory pointer to a c function In-Reply-To: References: Message-ID: On 1/29/22, Nathan Smith wrote: > > I actually managed to figure this out myself, but do have a related > question (I hope you all don't mind!). > > My solution was: > > import ctypes > data=b/"some text" > x=bytearray(data) > Buffer = ctypes.c_char * len(x) > buf = Buffer.from_buffer(x) > addr=ctypes.addressof(buf) > > My question is, do I need to free that buffer? Will python do it when > the object is deleted? buf is a buffer export of the bytearray. While `buf` is referenced, the bytearray remains allocated and cannot be resized. That said, the following is the typical way to create a mutable buffer from bytes data: buf = ctypes.create_string_buffer(data) This creates a ctypes.c_char array that's null terminated. All of the data is copied to the array, even if it contains null bytes. As a function argument, a C array is passed as a pointer to the first element, so you shouldn't need ctypes.addressof() in most cases. From david.l.blevins at comcast.net Mon Jan 31 16:00:53 2022 From: david.l.blevins at comcast.net (David Blevins) Date: Mon, 31 Jan 2022 16:00:53 -0500 Subject: [Tutor] Scripting Calligra sheets with Python In-Reply-To: References: Message-ID: <1858126b-958b-056c-fa8d-fea3227e1541@comcast.net> Jim, With Win 11 I'm looking to move from Micro$oft's Oz to Linux. The major hangup is several Excel workbooks with macros, from rather simple to super-complex. I've seen this: Can you tell me if there is a "manual/handbook" on Calligra scripting and point me to same? Thanx Here's an example of one of the macros I have: From johnf at jfcomputer.com Mon Jan 31 17:19:58 2022 From: johnf at jfcomputer.com (john fabiani) Date: Mon, 31 Jan 2022 14:19:58 -0800 Subject: [Tutor] Scripting Calligra sheets with Python In-Reply-To: <1858126b-958b-056c-fa8d-fea3227e1541@comcast.net> References: <1858126b-958b-056c-fa8d-fea3227e1541@comcast.net> Message-ID: <8dc16c68-10ee-6403-0ed8-ac118996de69@jfcomputer.com> I general I use Libre-calc.? I really don't have real complex macros.? But everything I have tried works without issue.? Also I use one of three python packages (xlrd,xlwt and openpyxl) for any kind of editing.? When I need to view the spreadsheet I use the os to open Libre-office (calc) to view the spreadsheet.? Printing also works. Johnf On 1/31/22 1:00 PM, David Blevins wrote: > Jim, > With Win 11 I'm looking to move from Micro$oft's Oz to Linux. The > major hangup is several Excel workbooks with macros, from rather simple to > super-complex. > > I've seen this: > > Can you tell me if there is a "manual/handbook" on Calligra scripting and > point me to same? > > Thanx > > Here's an example of one of the macros I have: > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor