Re: Cprod -- (writing this: itertools.product([0, 1], repeat=N )
On 22/05/24 07:14, HenHanna via Python-list wrote: How can i write this function Cprod (Cartesian Product) simply? (writing this out: itertools.product([0, 1], repeat=N ) The value can be a list or a Tuple. cprod([0, 1], 1) => ((0) (1)) cprod([0, 1], 2) => ((0,0) (0,1) (1,0) (1,1)) This works: def cprod(x, c): if c==1: return [[i] for i in x] Sub= cprod(x, c-1) return [i for F in x for i in [[F]+R for R in Sub]] -- Is there another way to write [F]+R ??? Other ways to improve it? https://python.readthedocs.io/en/stable/library/itertools.html#itertools.product -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Data Ethics (Virtual) Meeting
Virtual meeting, Wed 17 April, 1800 for 1830 (NZST, ie 0630 UTC) Data Ethics Emma McDonald is the Director of the Interim Centre for Data Ethics and Innovation at Stats NZ (New Zealand Government Department of Statistics) Emma will talk about why Stats NZ is establishing a Centre for Data Ethics and Innovation, and why it needs to be set up as a network that draws on and leverages knowledge and expertise across relevant work programmes and people across agencies. As an initiative, the Centre is there to help agencies develop and maintain secure and trusted data environments. A large part of this is drawing on a diverse network of people who can support the with sharing the importance of data ethics being a critical component of data driven technologies. Will be of-interest to Quants, Data Science, and Machine Learning folk; as well as those of us with wider interest in what should/not happen with personal, public, and corporate data... She will be wanting to hear what folk have to say, and is interested to recruit competent individuals for hui*, consultations, and the like. WebRef: https://data.govt.nz/leadership/the-interim-centre-for-data-ethics-and-innovation/ from which you can access their Work Programme and Guidance developed to-date. Please RSVP at https://www.meetup.com/nzpug-auckland/events/299764076/ * hui is the Te Reo Maori word for meeting or conference (Te Reo is one of New Zealand's official languages) -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: How to Add ANSI Color to User Response
On 11/04/24 06:50, WordWeaver Evangelist via Python-list wrote: I have a simple question. I use the following textPrompt in some of my Jython modules: '\n[1;33mYour choice is? (A B C D E): ', maxChars=1, autoAccept=False, forceUppercase=True) Is there a way to add an ANSI color code to the end where the conditions are, so that the color of the user’s input is of a color of my choosing, instead of just white? Thank you very much in advance. Kind regards, Bill Kochman Haven't tried using any of theses techniques, but may define input() color, as well as print():- How to print colored terminal text in Python MAR 06, 2024 ... https://byby.dev/py-print-colored-terminal-text -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Multiplication
The April Fools joke was on those of us who never received/have yet to receive @Stefan's OP. On 2/04/24 08:02, Avi Gross via Python-list wrote: Is this a April 1 post for fools. Multiplication with an asterisk symbol is built into python. The same symbol used in other contexts has other contexts has an assortment of largely unrelated meanings such as meaning everything when used to import. On Mon, Apr 1, 2024, 1:27 PM Piergiorgio Sartor via Python-list < python-list@python.org> wrote: On 01/04/2024 10.40, Stefan Ram wrote: Q: How can I multiply two variables in Python? I tried: a = 2 b = 3 print( ab ) but it did not work. A: No, this cannot work. To multiply, you need the multiplication operator. You can import the multiplication operator from "math": Code example: from math import * a = 2 b = 3 print( a * b ) I guess the operator "*" can be imported from any module... :-) bye, -- piergiorgio -- https://mail.python.org/mailman/listinfo/python-list -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: MTG: Introductions to PyQt and DataClasses
On 18/03/24 10:02, Jim Schwartz wrote: Actually, I have a sleep disorder that requires me to keep a constant sleep schedule. Thats why I asked. At a weekend meeting, discussion swirled around topics such as the best way to learn/work, how much work we should attempt in one sitting, could/should I 'do more', and similar. One of the valuable observations is that most of us would benefit by improving our sleep-schedule and ensuring we do sleep for sufficient time (probably longer than current habit). -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Configuring an object via a dictionary
On 18/03/24 04:11, Peter J. Holzer via Python-list wrote: On 2024-03-17 17:15:32 +1300, dn via Python-list wrote: On 17/03/24 12:06, Peter J. Holzer via Python-list wrote: On 2024-03-16 08:15:19 +, Barry via Python-list wrote: On 15 Mar 2024, at 19:51, Thomas Passin via Python-list wrote: I've always like writing using the "or" form and have never gotten bit I, on the other hand, had to fix a production problem that using “or” introducted. I avoid this idiom because it fails on falsy values. Perl has a // operator (pronounced "err"), which works like || (or), except that it tests whether the left side is defined (not None in Python terms) instead of truthy. This still isn't bulletproof but I've found it very handy. So, if starting from: def method( self, name=None, ): rather than: self.name = name if name else default_value ie self.name = name if name is True else default_value These two lines don't have the same meaning (for the reason you outlined below). The second line is also not very useful. the more precise: self.name = name if name is not None or default_value or: self.name = default_value if name is None or name Those are syntax errors. I think you meant to write "else" instead of "or". Yes, exactly. That's the semantic of Perl's // operator. JavaScript has a ?? operator with similar semantics (slightly complicated by the fact that JavaScript has two "nullish" values). Thanks Peter! (yes, sad consequences of suffering a neighbor's party-til-midnight followed by an 0530 meeting-start - children: don't code exhausted!) Herewith, an illustration of how the corrected version of the above works - and how (in what seem unusual cases) it avoids any truthy/falsy confusion, as raised earlier in this thread: >>> default_value = "default" >>> name = "Fred Flintstone" >>> name if name is not None else default_value 'Fred Flintstone' >>> name = None >>> name if name is not None else default_value 'default' >>> name = False >>> name if name is not None else default_value False >>> name = 1 >>> name if name is not None else default_value 1 >>> name = 0 >>> name if name is not None else default_value 0 Personally: I find the above coding more logical, because our primary interest is on 'the happy case', ie where the value has been assigned (to "name"); and the default_value is only applied as a "guard". On the other hand, I dislike the not-condition because it forces me to think (and maybe dust-off DeMorgan). Accordingly: >>> name = "Fred Flintstone" >>> default_value if name is None else name 'Fred Flintstone' >>> name = None >>> default_value if name is None else name 'default' >>> name = False >>> default_value if name is None else name False ... YMMV! NB your corporate Style Guide may prefer 'the happy path'... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: MTG: Introductions to PyQt and DataClasses
On 17/03/24 23:40, Jim Schwartz wrote: Will it be recorded? Better than that (assumption) "coming soon" - please join-up or keep an eye on PySprings' Meetup ANNs: https://www.meetup.com/pysprings/ On Mar 17, 2024, at 1:47 AM, dn via Python-list wrote: The Auckland Branch of NZPUG meets this Wednesday, 20 March at 1830 NZDT (0530 UTC, midnight-ish Tue/Wed in American time-zones), for a virtual meeting. Part 1: Learn the basics of PyQt with code examples. Hannan Khan is currently consulting as a Data Scientist for the (US) National Oceanic and Atmospheric Administration. He holds a Bachelor's degree in Neuroscience as well as a Masters in Computer Science. As a keen member of the PySprings Users' Group (Colorado), his contribution is part of a collaboration between our two PUGs. Part 2: Why use Dataclasses? - will be the question asked, and answered, by yours truly. After surveying a number of groups, it seems most of us know that Dataclasses are available, but we don't use them - mostly because we haven't ascertained their place in our tool-box. By the end of this session you will, and will have good reason to use (or not) Dataclasses! Everyone is welcome from every location and any time-zone. The NZPUG Code of Conduct applies. JetBrains have kindly donated a door-prize. Our BigBlueButton web-conferencing instance is best accessed using Chromium, Brave, Vivaldi, Safari, etc, (rather than Firefox - for now). A head-set will facilitate asking questions but text-chat will be available. Please RSVP at https://www.meetup.com/nzpug-auckland/events/299764049/ See you there! =dn, Branch Leader -- https://mail.python.org/mailman/listinfo/python-list -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
MTG: Introductions to PyQt and DataClasses
The Auckland Branch of NZPUG meets this Wednesday, 20 March at 1830 NZDT (0530 UTC, midnight-ish Tue/Wed in American time-zones), for a virtual meeting. Part 1: Learn the basics of PyQt with code examples. Hannan Khan is currently consulting as a Data Scientist for the (US) National Oceanic and Atmospheric Administration. He holds a Bachelor's degree in Neuroscience as well as a Masters in Computer Science. As a keen member of the PySprings Users' Group (Colorado), his contribution is part of a collaboration between our two PUGs. Part 2: Why use Dataclasses? - will be the question asked, and answered, by yours truly. After surveying a number of groups, it seems most of us know that Dataclasses are available, but we don't use them - mostly because we haven't ascertained their place in our tool-box. By the end of this session you will, and will have good reason to use (or not) Dataclasses! Everyone is welcome from every location and any time-zone. The NZPUG Code of Conduct applies. JetBrains have kindly donated a door-prize. Our BigBlueButton web-conferencing instance is best accessed using Chromium, Brave, Vivaldi, Safari, etc, (rather than Firefox - for now). A head-set will facilitate asking questions but text-chat will be available. Please RSVP at https://www.meetup.com/nzpug-auckland/events/299764049/ See you there! =dn, Branch Leader -- https://mail.python.org/mailman/listinfo/python-list
Re: Configuring an object via a dictionary
On 17/03/24 12:06, Peter J. Holzer via Python-list wrote: On 2024-03-16 08:15:19 +, Barry via Python-list wrote: On 15 Mar 2024, at 19:51, Thomas Passin via Python-list wrote: I've always like writing using the "or" form and have never gotten bit I, on the other hand, had to fix a production problem that using “or” introducted. I avoid this idiom because it fails on falsy values. Perl has a // operator (pronounced "err"), which works like || (or), except that it tests whether the left side is defined (not None in Python terms) instead of truthy. This still isn't bulletproof but I've found it very handy. So, if starting from: def method( self, name=None, ): rather than: self.name = name if name else default_value ie self.name = name if name is True else default_value the more precise: self.name = name if name is not None or default_value or: self.name = default_value if name is None or name because "is" checks for identity, whereas "==" and True-thy encompass a range of possible alternate values? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Configuring an object via a dictionary
On 16/03/24 21:15, Barry via Python-list wrote: On 15 Mar 2024, at 19:51, Thomas Passin via Python-list wrote: I've always like writing using the "or" form and have never gotten bit I, on the other hand, had to fix a production problem that using “or” introducted. I avoid this idiom because it fails on falsy values. As with any other facility, one has to understand ALL implications! It must be one of those intensely-frustrating errors to track-down, which is then oh-so-simple to fix! Are you able to list (real, if suitably anonymised) examples of where the truthy/falsy was inappropriate, please? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Configuring an object via a dictionary
On 15/03/24 22:30, Loris Bennett via Python-list wrote: Hi, I am initialising an object via the following: def __init__(self, config): self.connection = None self.source_name = config['source_name'] self.server_host = config['server_host'] self.server_port = config['server_port'] self.user_base = config['user_base'] self.user_identifier = config['user_identifier'] self.group_base = config['group_base'] self.group_identifier = config['group_identifier'] self.owner_base = config['owner_base'] However, some entries in the configuration might be missing. What is the best way of dealing with this? How do you define "missing"? Thus, @Thomas' suggestion may/not apply. It is neat and easy. I usually plump for: self.source_name = config[ "source_name" ] or default_value but @Grant's warning applies! (which is why the pythonic way is to use (and test for) None as a definition of "missing" (see also impacts of using default values and mutable data-structures) LBYL cf EAFP: When setting-up an environment like this, elements are often set to a default-value, and then user-settings, command-line arguments, and the like, applied in a priority-order sequence, amend as-appropriate. In this way, such problems will never arise. This is the better course 90% of the time. Which raises the next question: What is the impact if some attribute is "missing"? ie if the 'whatever' must be identified by source_name (for example), then there is little point in assigning any values to the new class. Considerations which apply *after* this question, the __init__(), are at least equally-important considerations (see below)! I could of course simply test each element of the dictionary before trying to use. I could also just write self.config = config but then addressing the elements will add more clutter to the code. By which you mean that such "clutter" should only appear in the __init__() - which is not such a bad idea (but see below). OTOH it is often helpful to one's comprehension to be given a prompt as to the source of the data. Thus, in later processing *config[ "source_name" ] may add a small amount of extra information to the reader, over self.source_name. * maybe prepended "self.", or not... Am assuming that passing all eight elements as individual arguments is off-the-table, embodying far too many 'negatives' (see below). However, with a view to asking forgiveness rather than permission, is there some simple way just to assign the dictionary elements which do in fact exist to self-variables? Assuming config is a dict: self.__dict__.update( config ) will work, but attracts similar criticism - if not "clutter" then an unnecessary view (and understanding) of the workings of classes under-the-hood. Another question: When these values are used, are they all used at the same time, and never again? It may only be worth 'breaking-out' and making attributes from those which are used in multiple situations within the class's methods. If, the other extreme, they are only (effectively) passed from the __init__() to some sort of open() method, then pass the data-structure as an whole and delegate/remove the "clutter" to there. In that scenario, such detail would *only* has meaning *and* purpose in the open() method and thus no point in cluttering-up the __init__() with detail that is only required elsewhere! Or should I be doing this completely differently? YMMV, but I prefer the idea of transferring the environment/config as a whole (as above). If it were a class (cf the supposed dict) then "clutter" is reduced by eschewing brackets and quotation-marks, eg "config.source_name". If those eight-elements are not the entirety of that data-structure, then consider creating an interface-class, which is extracted (or built that way) from some wider 'environment', and used to set-up access to data-source(s) or whatever. Again, this aids understanding in knowing where data has been created/gathered, and improves confidence when utilising it down-the-line. The other principle in only providing the required (eight) items of data, is that the 'receiving-class' needs no understanding of the structure or workings of the 'sending-class' = separation of concerns, and each class has single purpose/reason to change. A variation on that might be to use a method/function as the interface: access = Access( config.access_data ) Thus, the config class (instance) will need an access_data method to collate the data-items. The complimentary code in this Access.__init__( self, config, ) might be something like: ( self.source_name, self.server_host, self.server_port, self.user_base, self.user_identifier, self.group_base,
Re: A Single Instance of an Object?
Good question Rambius! On 12/03/24 09:53, Ivan "Rambius" Ivanov via Python-list wrote: Hello, I am refactoring some code and I would like to get rid of a global variable. Here is the outline: import subprocess CACHE = {} First thought: don't reinvent-the-wheel, use lru_cache (https://docs.python.org/3/library/functools.html) The global cache variable made unit testing of the lookup(key) method clumsy, because I have to clean it after each unit test. I refactored it as: class Lookup: def __init__(self): self.cache = {} Change "cache" to be a class-attribute (it is currently an instance. Then, code AFTER the definition of Lookup can refer to Lookup.cache, regardless of instantiation, and code within Lookup can refer to self.cache as-is... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference
On 7/03/24 05:28, Jacob Kruger via Python-list wrote: ... So, yes, know this comes across like some form of a scam/joke, or list-garbage, since it doesn't make any sense to me at all, but still just wondering if missing something, or should I shift over to 3.12 to see if if works differently, or just try reinstalling 3.11 from scratch, or should I retry the above in something like the VS code console, or a different python console, etc.? Some of the facts, such as HOW the code was being executed were missing (see earlier request for a cut-down scenario, AND reports from others saying 'but it works for me'). The idea of importing a module into the REPL and then (repeatedly) manually entering the code to set-up and execute is unusual (surely type such into a script (once), and run that (repeatedly). As you say, most of us would be working from an IDE and hitting 'Run'. Am wondering why you weren't - but it's not important. That said, the REPL is the perfect place to learn, experiment, and prototype - particularly when compared with the facilities of other language's eco-systems. The entirety of the on-line Tutorial cannot be wrong! (although, after a quick review, I've failed to see where the Tutorial mentions the usual development mode, apart from two very brief asides (the most useful is almost at the very end(?)) - but then (as they say) the objective is to show the language! The lesson-learned is that there are different 'environments' and different ways of building the environment in which the code will run. That's a valuable lesson, and full of subtlety! Glad to see that comparing id()s was useful - for diagnosis but not solution. Other tools might include the locals() and globals() functions. You may also have detected that many of us try to avoid globals and the implicit assumptions about the behavior of mutable collections (eg lists) when treated as 'global'. Then there are "closures", the "LEGB" rule, namespaces, scope, and ... -- -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Variable scope inside and outside functions - global statement being overridden by assignation unless preceded by reference
Jacob, Please reduce the problem to a small code-set which reproduces the problem. If we can reproduce same, then that tells us something. At the very least, we can experiment without having to expend amounts of time in a (likely faulty) bid to reproduce the same environment. Also, code is the ultimate description! Perhaps start with a small experiment: - after l_servers is created, print its id() - after the global statement, print its id() - after the clear/reassignment, print its id() Is Python always working with the same list? Please advise... On 6/03/24 07:13, Jacob Kruger via Python-list wrote: Hi there Working with python 3.11, and, issue that confused me for a little while, trying to figure out what was occurring - unless am completely confused, or missing something - was that, for example, when having pre-defined a variable, and then included it in the global statement inside a function, that function was still referring to a completely local instance, without manipulating outside variable object at all unless I first executed a form of referral to it, before then possibly assigning a new value to it. Now, this does not seem to occur consistently if, for example, I just run bare-bones test code inside the python interpreter, but consistently occurs inside my actual testing script. Basically, in a file with python code in that am using for a form of testing at the moment, at the top of the file, under all the import statements, I initiate the existence of a list variable to make use of later: # code snippet l_servers = [] # end of first code snippet Then, lower down, inside a couple of different functions, the first line inside the functions includes the following: # code snippet global l_servers # end code snippet That should, in theory, mean that if I assign a value to that variable inside one of the functions, it should reflect globally? However, it seems like that, while inside those functions, it can be assigned a new list of values, but if I then return to the scope outside the functions, it has reverted back to being an empty list = []? The issue seems to specifically (or not) occur when I make a call to one function, and, in the steps it's executing in one context, while it's not doing anything to the list directly, it's then making a call to the second function, which is then meant to repopulate the list with a brand new set of values. Now, what almost seems to be occurring, is that while just manipulating the contents of a referenced variable is fine in this context, the moment I try to reassign it, that's where the issue is occurring . Here are relevant excerpts from the file:- # start code # original assignation in main part of file l_servers = [] # function wich is initially being executed def interact(): global l_servers # extra code inbetween choosing what to carry out # ... # end of other code bl_response, o_out = list_servers() if bl_response: # just make sure other function call was successful l_servers.clear() # first make reference to global variable for srv in o_out: l_servers.append(srv) # now re-populate items # end code snippet from inside interact function # end of interact function # end of code snippet That other function being called from within, list_servers() was initially just trying to populate the values inside the global list variable itself, but was ending up in a similar fashion - reverting to initial empty value, but, the above now seems to work, as long as I first make reference to/manipulate/work with global variable instead of just trying to reassign it a brand new value/set of items? So, am I missing something obvious, have I forgotten about something else - yes, know that if was working from within an embedded function, I might need/want to then use the nonlocal statement against that variable name, but, honestly, just not sure how this can be occurring, and, it's not just with this one list variable, etc.? If I try simple test code from within the python interpreter, using different types of variables, this does also not seem to be the same all the time, but, don't think it can relate to an iterable like a list, or else, just in case, here is the code snippet with all the import statements from the top of that file, in case something could be overriding standard behaviour - not likely in this context, but, really not sure what's occurring: # import code snippet import requests, time from requests.auth import HTTPBasicAuth import psutil as psu import pytz import bcrypt from copy import copy from datetime import datetime, timedelta, timezone from dateutil.parser import parse # end of import snippet Thanks if you have any ideas/thoughts on the matter Jacob Kruger +2782 413 4791 "Resistance is futile!...Acceptance is versatile..." -- Regards, =dn --
Re: Can one output something other than 'nan' for not a number values?
On 20/02/24 01:04, Chris Green via Python-list wrote: dn wrote: On 18/02/24 09:53, Grant Edwards via Python-list wrote: On 2024-02-17, Cameron Simpson via Python-list wrote: On 16Feb2024 22:12, Chris Green wrote: I'm looking for a simple way to make NaN values output as something like '-' or even just a space instead of the string 'nan'. [...] Battery Voltages and Currents Leisure Battery - 12.42 volts -0.52 Amps Starter Battery - nan voltsnan Amps What I would like is for those 'nan' strings to be just a '-' or something similar. The simplest thing is probably just a function writing it how you want it: def float_s(f): if isnan(f): return "-" return str(f) and then use eg: print(f'value is {float_s(value)}') or whatever fits your code. Except he's obviously using some sort of formatting to control the number of columns and decimal places, so 'str(f)' is not going to cut it. Is the basic floating point number formatting functionality seen when using f-strings or '%' operator part of the float type or is it part of the f-string and % operator? It's part of the PSL's string library: "Format Specification Mini-Language" https://docs.python.org/3/library/string.html#format-specification-mini-language Has the OP stated if we're talking 'Python' or numpy, pandas, ...? Just python, on a Raspberry Pi, so currently Python 3.9.2. Concur with earlier advice (and assuming is only a consideration during output) - use if. Alternately, encode appropriately during the data-capture phase. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Can one output something other than 'nan' for not a number values?
On 20/02/24 05:58, Grant Edwards via Python-list wrote: Here's a demonstration of how to hook custom code into the f-string formatting engine. It's brilliantly depraved. https://stackoverflow.com/questions/55876683/hook-into-the-builtin-python-f-string-format-machinery From the above: You can, but only if you write evil code that probably should never end up in production software. So let's get started! I'm not going to integrate it into your library, but I will show you how to hook into the behavior of f-strings. This is roughly how it'll work: 1. Write a function that manipulates the bytecode instructions of code objects to replace FORMAT_VALUE instructions with calls to a hook function; 2. Customize the import mechanism to make sure that the bytecode of every module and package (except standard library modules and site-packages) is modified with that function. Final code is here: https://github.com/mivdnber/formathack Some of this (Expression components inside f-strings) newly available in v3.12 (PEP-701) - which can be used in production... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Testing (sorry)
On 19/02/24 12:09, Grant Edwards via Python-list wrote: ... But posts to the list still seemed to vanish into the ether while emails from both accounts reached other destinations without delay, During this process a number of posts from other users did appear in the list archive and at at _one_ of the two e-mail addresses which I had subscribed. But no sign of any of my posts. About 24 hours later, all of my posts (and the confirmation e-mails) all showed up in a burst at the same time on two different unrelated e-mail accounts. I still have no clue what was going on... Looking at the email-headers, there are sometimes considerable delays between messages submitted to the List-reflector, and their outward transmission (to me). Interestingly, there's something strange about the queuing. Instead of FIFO it seems some messages arrive ahead of others, ie out-of-sequence. (wonder if explained by submission via email or Usenet?) I've noted long delays too. Perhaps (also) to do with time-of-day? Always feel slightly embarrassed if 'repeat' an answer* that someone else had previously submitted, eg __new__ thread and @MRAB. However, if the reflector 'holds onto' the earlier message, then how should I/anyone know? * yes, repetition improves learning, slightly different words may help comprehension; but doubt I can express anything better than the aforementioned does/did/can. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Can one output something other than 'nan' for not a number values?
On 18/02/24 09:53, Grant Edwards via Python-list wrote: On 2024-02-17, Cameron Simpson via Python-list wrote: On 16Feb2024 22:12, Chris Green wrote: I'm looking for a simple way to make NaN values output as something like '-' or even just a space instead of the string 'nan'. [...] Battery Voltages and Currents Leisure Battery - 12.42 volts -0.52 Amps Starter Battery - nan voltsnan Amps What I would like is for those 'nan' strings to be just a '-' or something similar. The simplest thing is probably just a function writing it how you want it: def float_s(f): if isnan(f): return "-" return str(f) and then use eg: print(f'value is {float_s(value)}') or whatever fits your code. Except he's obviously using some sort of formatting to control the number of columns and decimal places, so 'str(f)' is not going to cut it. Is the basic floating point number formatting functionality seen when using f-strings or '%' operator part of the float type or is it part of the f-string and % operator? It's part of the PSL's string library: "Format Specification Mini-Language" https://docs.python.org/3/library/string.html#format-specification-mini-language Has the OP stated if we're talking 'Python' or numpy, pandas, ...? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Using __new__
On 18/02/24 13:21, Jonathan Gossage wrote: The problem is that if you are dealing with a library class, you may have times when the superclass is 'object' while at other times, with a different inheritance hierarchy, the superclass may need arguments. My thought is that the object class __new__ method should not choke on arguments, just ignore them. All true. So, what you're looking for is one mechanism to rule them all? Not going to happen: for exactly the reasons you've stated. If you really want to get right 'down into the weeds' with a __new__() constructor, then you're well into customisation-territory. I think it would be 'going nuts' but... If it 'absolutely, positively, ...' then perhaps introspect the super-class and modify the call based-upon whether it is 'something' or "object"? (in similar fashion to the singleton's if-statement attempting to make sure it is unique) - perhaps someone knows a better/proper way to do this? Suggested research: custom classes, ABCs, and meta-classes... See also recent improvements to Python which have made it easier for sub-classes (and Descriptors - __set_name__() ) to identify who/how/where to 'phone home', in case (also) applicable... When I talk about 'object', I am talking about the ultimate base class of any inheritance hierarchy. have seen the class named 'object' called that. Correct. The earlier comment was that class S( object ): is 'tradition', and synonymous with: class S: (not disputing the concept of "object" as the base class) Not correct. Please see last paragraph from previous message: On Sat, Feb 17, 2024 at 7:06 PM dn via Python-list mailto:python-list@python.org>> wrote: ... PS please reply to the list - there may be others who can learn from, or contribute to, this conversation! ... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Using __new__
On 18/02/24 12:48, Jonathan Gossage wrote: The problem that I am facing is that when the superclass is not 'object', the __init__ method may well need arguments. I do not know how to determine if the superclass is 'object'. For what it is worth, any attempt to use this with different arguments should return the initial singleton and ignore further attempts to create a second instance. 1 "object" don't understand. Perhaps give us a broader description of the problem? Remember also ABCs (Abstract Base Classes). 2 arguments yes, must accommodate arguments in __new__() if some/same are needed in __init__() However, when using the default "object", the super() does not need, use, or want, any arguments to be passed. 3 singleton don't think that is happening! PS please reply to the list - there may be others who can learn from, or contribute to, this conversation! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Using __new__
On 18/02/24 11:35, Jonathan Gossage via Python-list wrote: I am attempting to use the __new__ method in the following code: class SingletonExample(object): _instance = None def __new__(cls, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls, **kwargs) return cls._instance def __init__(self, **kwargs) -> None: our_attributes = ('h', 'x') if kwargs is not None: for k, v in kwargs.items(): if k in our_attributes: setattr(self, k, v) a = SingletonExample(h=1) and I get the following result: (PRV) jonathan@jfgdev:/PR$ python -m Library.Testing.test2 Traceback (most recent call last): File "", line 198, in _run_module_as_main File "", line 88, in _run_code File "/mnt/ProgrammingRenaissance/Library/Testing/test2.py", line 16, in a = SingletonExample(h=1) ^ File "/mnt/ProgrammingRenaissance/Library/Testing/test2.py", line 6, in __new__ cls._instance = super().__new__(cls, **kwargs) ^^ TypeError: object.__new__() takes exactly one argument (the type to instantiate) I am quite puzzled as it looks as if this code will not work if the super-class is 'object'. Any suggestions on how to proceed? Don't be puzzled. Read the error-message. Change the super-call to: cls._instance = super().__new__(cls) and happiness will follow... That said, mystifications - not sure if this meets the/your definition* of "singleton", because: - it can be aliased, eg a = SingletonExample(h=1) b = SingletonExample(x=2) - when it is, the effect is an accumulation of attributes and values a = SingletonExample(h=1) b = SingletonExample(h=2) print( a.__dict__, b.__dict__, ) - it can be re-created with a different value, eg a = SingletonExample(h=1) a = SingletonExample(h=2) - and can be 'regenerated': a = SingletonExample(h=1) a = SingletonExample(x=2) - all failures are silent * noting "Nowadays, the Singleton pattern has become so popular that people may call something a singleton even if it solves just one of the listed problems." (https://refactoring.guru/design-patterns/singleton) YMMV! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: test-ignore
On 16/02/24 13:29, Skip Montanaro via Python-list wrote: Test post to see if my Newsgroup post program is working. Aim your test messages at alt.test, please. I agree that basic Usenet connectivity messages should go to alt.test. It's not clear from the original post, but if the poster's aim was to see if posts to comp.lang.python traverse the gateway and show up on this list, then alt.test won't help. Coincidentally (I hope), today have received a couple of poorly-executed spam/phishing messages purporting to be from this list or "Tutor". -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 4/02/24 13:20, avi.e.gr...@gmail.com wrote: Dave, You and I have had some experience in teaching or tutoring others and I think it fair to say our motivation is closer to teaching someone how they can fish for themselves rather than just handing them a fully-cooked fish. Which may push the debate 'up' a level, in that there are two pertinent Python Discussion Lists (amongst the many): Tutor which is expressly for learners (and tutors), and this one which is to discuss Python. Accordingly, one might suggest that people 'here' are looking for a direct answer - the fish (having tried to fish for themselves), but learners (seeking to learn to fish) should be asking elsewhere. This would sort-out the type/level of questions that OPs may have. As well as indicating an appropriate approach to 'answers'. However, there's no rule which says one has to ask in one place or the other (nor am I suggesting such, although...). Then again, might the lack of forethought evident in some questions and the forum-used, indicate a type of person who wouldn't investigate to see which is the best place for his/her enquiries anyway? Tutor List: https://mail.python.org/mailman/listinfo/tutor Lists Overview: https://mail.python.org/mailman/listinfo My favorite kinds of questions, thus, include someone who explains what they are trying to do and shows some code along with indications of what it produced (including error messages) and what it should produce. Then the question should not be a request to just FIX THIS or WRITE IT FOR ME but asking if someone can show what they did wrong with some idea where it went wrong. This may not be so common but it allows faster and easier help. +1 ... I will end with a comment. I have heard of interview techniques for a job where they deliberately supply a problem in which the goal is not so much to be easy to solve in front of them in real time but to watch how the person looking for a job responds to the uncertainties and asks follow-up questions or verbalizes things like, if it is like this, I might use this technique but if you also need that then ... So, I shudder to think what happens if someone being interviewed turns around and asks us and further confuses things with changes to make it harder to recognize they are asking for outside help. The answer expected may well be to NOT use say the older versions of PASCAL to do something but switch to something better suited (and for that matter available.) I would not want to program the DES encryption/decryption method in Pascal again! And these days, it seems much better to just find a module or package that meets such needs. As you know, I investigate Cognitive Psychology. Accordingly, such is interesting to me. In many cases, I'll interview for motivation, not just particular skills - but perhaps that's another can-of-worms. How about "when is 1 + 1 not 2?". This is a bit of a mind-bender, but leads towards debugging ability* - what if your code was showing some unbelievable result like this? The answer is (or rather, "could be") 10, ie we're looking at binary cf decimal, coding. Do I hear some groans? Yes, fair-enough! There was absolutely no "context" to the question - whereas when coding/debugging we would expect to have some 'framing' of our thinking. At the same time, 'fixed mode thinking' will prevent many people from even considering such possibilities - whether as-asked or in a dev.env... * In the ?good old days, career progression was thought to be: (mainframe) Computer Operator, to Computer Programmer, to Systems Analyst, etc. However, as I pointed-out (to an IBM 'big-wig' who took an instant dislike as a result) the valued skills of an Analyst are that (s)he can see 'patterns' - whereas the skills of debugging involve realising why an expected pattern doesn't work (as-expected). Another analysis might be to decide if the job requires a 'lateral thinker' or a more single-minded approach. (us lateral thinkers tend to ask (loads of) questions, and thus can be quite 'annoying' individuals). Then there is the main-stay of many job-adverts: "attention to detail" and the question of whether someone who can't [be bothered to] write an half-decent email-message (with spell-checker likely built-in) is going to be productive when communicating with a pedantic compiler? Again, some people are suited to this business (or specific jobs within), and some (?many) are not - but many are (perhaps reluctantly) programming to get some other job done... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
Every trainer, in any field, has to deal with these problems - all the time, and over-and-over. On 4/02/24 06:58, Thomas Passin via Python-list wrote: In my view this whole thread became murky and complicated because the OP did not write down the requirements for the program. Requirements are needed to communicate with other people. An individual may not need to actually write down the requirements - depending on their complexity - but they always exist even if only vaguely in a person's mind. The requirements may include what tools or languages the person wants to use and why. If you are asking for help, you need to communicate the requirements to the people you are asking for help from. The OP may have thought the original post(s) contained enough of the requirements but as we know by now, they didn't. There is another possible interpretation in such situations (not necessarily this one): that the person is fixated on a particular solution (and unable/unwilling to adjust his/her thinking to consider more widely). Thus, the question is not: 'here's an entire problem, how can it be solved', but more: 'I have a solution, and want help to implement it (and only it) just-so'. The latter is an interesting psychology: 1 an experienced person who is trying to translate from one tool to another (Python), but discovers that a word-for-word solution is difficult because of the artificial-constraints they've placed on the situation. 2 a beginner who doesn't know what (s)he doesn't know and comes-up with an idea, but fails to appreciate that there is likely more than one path to the goal. The person asking for help may not realize they don't know enough to write down all the requirements; an effort to do so may bring that lack to visibility. In the case of 'Beginners' this should probably be taken-as-read! Which is why we will always find ourselves asking questions or 'please give more information'... However, there are other reasons, eg corporate concerns or personality; why people don't want to give more information. The former is reasonable (have suffered from same myself). The latter may reveal that the person is 'difficult to deal with'... Mailing lists like these have a drawback that it's hard to impossible for someone not involved in a thread to learn anything general from it. We can write over and over again to please state clearly what you want to do and where the sticking points are, but newcomers post new questions without ever reading these pleas. Then good-hearted people who want to be helpful end up spending a lot of time trying to guess what is actually being asked for, and maybe never find out with enough clarity. Others take a guess and then spend time working up a solution that may or may not be on target. So please! before posting a request for help, write down the requirements as best you can figure them out, and then make sure that they are expressed such that the readers can understand. Unfortunately, if the person doesn't understand the problem (leave-aside any ideas of solution), then (s)he will not be able to clearly communicate same to us, in any way, shape, or form... Which brings one to the question: if a person cannot express the problem clearly and completely, is (s)he suited to development work? If the problem is not understood, could 'the solution' ever be more than an exercise in hope? (prototyping and experimentation aside) Yes, it is frustrating to invest time and effort in helping someone, only for same to disappear 'into a black hole'. The lack of response seems to indicate a lack of respect or appreciation. Is this perhaps part of today's "consumer" life-style, where so few are contributors or creators? On the other side of that coin: do the people who make assumptions and (kindly) blaze-ahead with 'a solution', actually help the conversation? If the assumptions are correct, yes! What if they are not? ...and don't get me started on folk who want us to do their training-assignments or build some application, for them! As a slight aside: on one training-course DiscussionList/BulletinBoard set-up, if a trainee asked a question without a descriptive title/SubjectLine, eg "Python not working" or "Urgent: please help"; I asked them to re-post with a title that would help others in a similar situation find the topic - and closed the original thread. Some found it "brutal" - probably skewing towards those who felt "Urgent" because they'd left things too close to deadline. Others joined the (later) thread because they could identify the topic and realise their interest in learning or contributing to the conversation... Time pressures lead to a multitude of evils! There's a quotation that goes something like "the poor will be with your always"? (?possibly Biblical) Whether we (here) are talking about 'poor' manners, 'poor' understanding, 'poor' communication skills, 'poor'
MTG: pytest (NZPUG, Auckland, VacExcHndlrs)
Wed 7 Feb (evening NZDT) will be the last virtual gathering in the current Vacation Exception Handlers (VacExcHndlrs) series (https://danceswithmice.info/Python/2024/VacExcHndlrs.html). You are cordially-invited to join us to investigate the pytest Python testing framework. "The pytest framework makes it easy to write small, readable tests, and can scale to support complex functional testing for applications and libraries." Pre-requisites: 1 Head-set to ask questions and make contributions 2 Lab-/Log-/Note-book 3 Python 3.8+ installed 4 Ability to write intro-level Python program[me]s (at least) 5 Credentials to install from PyPi ("The Cheese Shop") 6 Preparedness to research, experiment, work with others... As before, we will follow a café style of meeting. So, come prepared with a list of objectives you would like to achieve and a list of achievements you will be ready to share. Possible (but far too many) topics: - installing pytest (individual, system-wide, PyCharm, VSCodium, ...) - TDD's (Test-Driven Development) red-green refactoring - the Python assert-statement - the project directory-tree and auto-discovery - adding simple-tests - running pytest - reporting - structuring the code-base to facilitate testing - advantages/disadvantages of automated testing - using a GAI to suggest/generate tests - fixtures and dependencies (set-up and/or tear-down) - scopes (function, class, module, session) - parametrizing - monkey-patching - CI/CD chaining you've built - plug-ins you're finding helpful - coverage - testing strategies - other testing frameworks and aids (open-ended - what would you like to add?) Come to participate, learn-from, and help others! Please RSVP at https://www.meetup.com/nzpug-auckland/events/298901851/ -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 30/01/24 05:15, Rich Shepard via Python-list wrote: On Fri, 12 Jan 2024, Rich Shepard via Python-list wrote: For my use 1) the salutation and email address (always with an '@') are sequential and 2) I'm developing the script to extract both from the same file. I've looked at my Python books "Python Crash Course," "Effective Python," and "Python Tricks The Book" as well as web pages in my searches without finding the answer to what may be a simple question: how to specify a variable in one file that has its values in another file. Specifically, how to I designate the salutation holder in the message file and pass it the name value from the name/email address file? If this explanation is not sufficiently clear I'll re-write it. :-) It seems clear - but maybe we (all) misunderstand? The books don't cover it - but is there a reason why they don't? (Thunderbird did not thread this message with earlier ones, and it seems some time has passed/memory is fading - but hopefully have remembered content) As said previously, the idea of two physical-files containing logically-related data (without any form of cross-reference between) is bad design. In the current file, there is one physical structure and each person's details are logically-related by proximity. A long way from ideal, but workable (as you've described). However, once split into two files, there is no way to guarantee that the two logically-related data-items (name and address) will continue to be related by their physical position in the respective files. Worse: whilst it would seem apparent that "Alice" from the names file might be related to the address "al...@domain.tld", how could one know if "Bob" actually corresponds to "list-mem...@domain.tld"? This is why dicts, databases, etc, offer keys (as labels for data-items/dependent components)! After a quick look at Eric's Crash Course, yes, his files-intro example (digits of pi) is unlikely to have any practical reality (and I work with statisticians and quants!). However, at the end of that chapter (10), there is mention of JSON files. A JSON version of the existing single-file structure will provide human-readable labeling of data-items, give better separation between individuals' data, and show how name and address are linked. Recommend solving 'the problem' that way! (as previously discussed by others 'here', IIRC) Slatkin's Effective Python doesn't seem to discuss the basics of files at all (presumes such knowledge of the reader). It dives into important, but rather technical discussions, comparing strings and bytes - somewhat beyond the complexity-level of this discussion. That book does however include discussions such as "Prefer Multiple Assignment Unpacking over Indexing" (Item 6 - also points to Item 19) where relative-positioning (indexing in other words) is advised-against. If you wish to persist with this two-file structure, please see earlier responses (again, IIRC) and discussion of file-merge operations. As these date back to mainframes and the days of storing files on mag-tape, I'd be surprised to see them discussed in 'modern' texts. However, the principle is: read a record from each file, do-the-business, read the next 'pair' of physically-related records, rinse-and-repeat. If you require further assistance: how about showing a couple of relevant lines of the data-file(s) and the pertinent parts of the code, along with a description of what's going-wrong or not making sense to you? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 15/01/24 21:13, Greg Ewing via Python-list wrote: On 15/01/24 1:54 pm, dn wrote: Soon after, Wirth simplified rather than expanded, and developed Pascal. Before Pascal there was Algol-W, which Wirth invented as a rebellion against how complicated Algol 68 was becoming. When I first saw this I was stunned, then attracted to its simplicity, but then steered-away once realised that it needed 'more' to cope with 'the outside world'. Pascal was intended as a teaching language, and as such it was lacking in practicality in a few spots. But it didn't need much tweaking to make it a very useful language. UCSD Pascal, Turbo Pascal, Delphi, etc. enjoyed a lot of popularity. A variant of UCSD was the main language for Macintosh application development for a number of years. Ironically, I didn't come across Pascal as a teaching-language. Borland were trying to turn Turbo Pascal into a practical development environment, beyond teaching (as with others of their 'Turbo' series). As I say, it didn't float my business-world boat. - not before I won a case a wine from Philippe Kahn's own vineyard for solving some 'interview question' and exchanging jokes with him, in French, at some Trade Show in London. Two surprises: one, that it actually turned-up a few weeks later, and two, that I (suddenly) had so many friends! Ah, the good, old days... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 15/01/24 14:45, Chris Angelico wrote: On Mon, 15 Jan 2024 at 12:42, dn via Python-list wrote: On 15/01/24 14:33, Chris Angelico via Python-list wrote: On Mon, 15 Jan 2024 at 12:12, dn via Python-list wrote: Here's another witticism I'll often toss at trainees (in many languages, and especially in UX): just because we can do it, doesn't make it a good idea! Programming. We were so busy with whether we COULD that we didn't stop to think if we SHOULD. I think that's basically my whole life. Don't be too hard on yourself. My life-advice has always been "don't do anything I wouldn't do" - which pretty-much gives you carte blanche. I would NEVER give that advice to anyone. They would leave the dishes unwashed, and a number of other problems :) I'd soon have you sorted-out - except for one small problem: all the dishes have been done! If you can get here before the rain, the lawn needs mowing... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 15/01/24 14:33, Chris Angelico via Python-list wrote: On Mon, 15 Jan 2024 at 12:12, dn via Python-list wrote: Here's another witticism I'll often toss at trainees (in many languages, and especially in UX): just because we can do it, doesn't make it a good idea! Programming. We were so busy with whether we COULD that we didn't stop to think if we SHOULD. I think that's basically my whole life. Don't be too hard on yourself. My life-advice has always been "don't do anything I wouldn't do" - which pretty-much gives you carte blanche. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 15/01/24 11:47, Chris Angelico via Python-list wrote: On Mon, 15 Jan 2024 at 09:40, dn via Python-list wrote: The basic challenge came from my earlier (and blasé) repetition of the Python refrain "everything in Python is an object". Which led to: ... So, no, there's an "everything" which (might be) an object but which cannot be used in that scenario. More accurately, every VALUE in Python is an object. This does not mean that syntax is an object. Very few languages would say that every single grammatical element is a value. +1 Thank you. This old-dog will try to re-learn that term... Yes, it's sloppy to say "everything" is an object, but it's also rather nonintuitive to claim that, therefore, syntax elements are all objects. It's like claiming that everything that this dealership sells is a car (or "everything in this dealership is a car"), and therefore the dealership's name must itself be a car. To say nothing of 'extended warranties'! (and their dubious rationale) That said, does anyone think that something like: for a_function( etc ) in iterable/iterator: is acceptable? - see both Python definition and (full-)quotation. I've not come-across a language which does allow such - YMMV/mea culpa; and am struggling to see how it could possibly be useful. You could do something close to that: for a_function(etc)[0] in iterable: ... because an assignment target can contain an arbitrary expression followed by the subscript. Here's another witticism I'll often toss at trainees (in many languages, and especially in UX): just because we can do it, doesn't make it a good idea! * Looking at the correspondent's email-address (cf 'handle') - and as an unfair stereotype, raises the question of issues related to (English) language-skills - which, arrogantly implies/assumes that native English-speakers are all highly-capable. (?) A negative-interpretation is to note his apparent intelligence, but wonder if failing to represent others' comments fairly is deliberate, or carelessness. Is there an irony in behaving/failing in such, whilst attempting to hold Python's structure to some golden-ideal? Seems likely. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 15/01/24 08:06, AVI GROSS via Python-list wrote: ...> You provided a way to create an anonymous function and that was not enough. I wonder if you could throw in the new := walrus operator to similarly make a named lambda function in a similar way. Why would @Chris have anything to do with the 'walrus-operator'? PS our interlocutor doesn't like colloquialisms such as these - despite them being near-and-dear to our hearts! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 15/01/24 01:28, Left Right wrote: Second time to ameliorate wording-dispute in this thread! The original phrase was: "[modified] BNF". Some of us have worked with various forms and evolutions of BNF since back in the days of COBOL-60 proposals, and know it when we see it! OK, here are the conceptual differences between what Python grammar language does and what you'd expect from anything that's based on BNF, modified or not: Python isn't a context-free language, so the grammar that is used to describe it doesn't actually describe the language... so, it's a "pretend grammar" that ignores indentation. BNF is supposed to be used to describe the language, it's not a "pretend" or "pseudo" grammar, in a way we have at least two established grammar for pseudo-code. BNF and derivatives don't have an inherent mechanism for tiebreaks. The mechanism is necessary because BNF rules can be tried in any order. Some grammar languages derived from BNF declare ambiguous grammars invalid, some allow ambiguity, but say that the longest prefix wins, and if there's still ambiguity after that, then such grammar is invalid, some have special constructs to define "priority" etc. My reading of Python grammar is that it works like PEG, where rules are tried in the order they are defined. This makes it less expressive, but easier to work with. This is, probably, the most fundamental difference between the BNF family and the PEG family. BNF and family languages rarely incorporate elements of Perl-like regular expression parsing in the language (i.e. things like lookaheads, lookbehinds etc.) This is more typical of the PEG family. On top of this, the Python grammar language has a bunch of "inventions" that are unique to it (I've never seen any other grammar language use '.' in the same way Python uses it). So, there's that too. Having worked with a bunch of different grammar languages, the one used for Python isn't a recognizable BNF derivative. I think the authors used this as a description in the same way as today a lot of programmers would use the word "IDE" to describe any text editor or "REST" to describe any kind of server-client protocol over HTTP and so on. Or, how we'd use "Xerox" to name a copier machine, even if that company didn't manufacture it, and even if the tech used for copying is completely different. And that's why I wrote that the grammar is actually more like PEG, adding that it's neither, but seems to fall more into that later category. We are in broad-agreement. I'd enjoy the discussion, except that I can't see where it is leading or how it will benefit you... Where we seem to differ is the length of time we've been part of the Python-world. An important point is that languages are often described as 'living', because they evolve over time. I'm relieved to note that the youngsters in the family have stopped describing 'everything' as "awesome". That word, has taken-on aspects of the original meanings of "awful". The former being positive-factors, and the negative ascribed to the latter. However, we don't have to step far back into history to find that "awful" meant 'full of awe' or awe-inspiring - with no connotation of 'good' or 'bad'. There was no need for a word with opposite-meaning, apart from "mundane". Similarly, spoken-language often lacks precision. My CO, to this day, uses phrases like "all done" [with time for me to take a breath, followed by "except ...", eg "are we ready to leave for ...?". This drives me nuts. (the word "nuts" requires consideration too!) Thus, have learned to elicit the pertinent information with phrasing such as "what is left to be done?" rather than arguing the illogic between "all" and "except". Python is not different. We're currently looking at version 3.12, which implies three major iterations of the language. Accordingly, when it was a 'green fields project', what may have been a pure and elegant expression of a language, has become "acquisitive". Sometimes these additions-and-alterations have required compromise, eg lack of elegance. Sometimes, it has been realised that there is a flaw, and things need to be improved, even removed. You've made comments about BNF. Like Python, it is a 'language' (a bit of stretch, but...) which has also been pulled, poked, and perhaps contorted over time. It had a body of folk who understood its expression, and therefore it made sense to stick with some variation of it (even warts-and-all) rather than going with something 'new'. All of which creates the sorts of issues described. The PEG-parser is a comparatively-recent improvement - other aspects previously-mentioned. I'm not going to touch "Perl". Is there really some sort of standard-understanding/format for "pseudo-code"? (ISO?) Yes, there's some 'pretense' (not sure I'd choose that exact term). However, it is working for the vast-majority. Perhaps after using Python for so long, I'm comfortable accepting such
Re: Extract lines from file, add to new files
On 15/01/24 10:23, Chris Angelico via Python-list wrote: On Mon, 15 Jan 2024 at 08:15, Left Right wrote: Python grammar rules prevent function definition from appearing in left-hand side of the head of the for loop. However, a variable declaration, which is also a statement, is allowed there. What is a "variable declaration" in Python? Please elaborate. We may be in danger of disappearing down an unintended 'rabbit hole' with this side-discussion (he says, with graceful under-statement). The basic challenge came from my earlier (and blasé) repetition of the Python refrain "everything in Python is an object". Which led to: <<< For example, you may say "functions in Python are objects", but you cannot put a function definition in the head of the for loop clause. >>> Which is logical - to some degree, and in-isolation. for def a_function( etc )... in iterable/iterator: does not make sense. The 'head' (a more generic name, where Python says "target_list", that refines down to 'something which can identify the generated-value'. So, no, there's an "everything" which (might be) an object but which cannot be used in that scenario. Two "howevers": However, instead of looking at the narrow clause, (third comment about wording not being taken as an whole!!!)* the full quotation was: <<< In Python, everything is an object. As long as the LHS is a legal-object which makes sense for the situation, it can be used. >>> Context! However, from the docs: "A function definition defines a user-defined function object (see section The standard type hierarchy)". Accordingly, is a function-definition an object? No! It defines an object. That said, does anyone think that something like: for a_function( etc ) in iterable/iterator: is acceptable? - see both Python definition and (full-)quotation. I've not come-across a language which does allow such - YMMV/mea culpa; and am struggling to see how it could possibly be useful. In-turn, how this discussion could become profitable... * Looking at the correspondent's email-address (cf 'handle') - and as an unfair stereotype, raises the question of issues related to (English) language-skills - which, arrogantly implies/assumes that native English-speakers are all highly-capable. (?) A negative-interpretation is to note his apparent intelligence, but wonder if failing to represent others' comments fairly is deliberate, or carelessness. Is there an irony in behaving/failing in such, whilst attempting to hold Python's structure to some golden-ideal? Web.Refs: https://docs.python.org/3/reference/compound_stmts.html#the-for-statement https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-target_list https://docs.python.org/3/reference/compound_stmts.html#function-definitions -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 14/01/24 16:48, Chris Angelico wrote: On Sun, 14 Jan 2024 at 14:43, dn via Python-list wrote: Similarly, whilst we could write: a, b, c = 1, 2, 3 I would only do this when it aligns particularly well with the algorithm being implemented. For example, you could start a Fibonacci evaluator with "a, b = 0, 1". Otherwise, there's not all that much reason to unpack three constants in this way. (Though I am much more likely to use multiple initialization to set a bunch of things to the SAME value, lilke "a = b = c = 0".) Neatly stated! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 13/01/24 00:11, Left Right via Python-list wrote: To people discussing BNF: The grammar language Python uses is *very* far from BNF. It's more similar to PEG, but even then it's still quite far. Python's grammar is just its own thing, which makes it harder to read, if you are already familiar with other more popular formats. Second time to ameliorate wording-dispute in this thread! The original phrase was: "[modified] BNF". Some of us have worked with various forms and evolutions of BNF since back in the days of COBOL-60 proposals, and know it when we see it! From the 'book of words': <>> https://docs.python.org/3/reference/introduction.html#notation Yes it is hard to read - and even harder to learn-from; which is why @Chris gave advice about preferring tutorials/text. Just because there are other (more popular?) formats, doesn't make the one used here 'wrong'. In the same way that Python code differs from 'the same' in other languages. Putting it another way: if what Python is doing is wrong in your opinion, you are in the wrong place (for you). That is not to say that Python has everything 'right'. One of my own bug-bears is very similar - that the string formatting 'mini-language' (https://docs.python.org/3/library/string.html#formatspec) does not follow the same rules about white-space as everything covered by the PEG Parser. BTW the PEG Parser is relatively new to Python. IIRC there was comment at the time of its first application, that some 'other' areas of Python might take a while to be converted-over. I've also found bugs in Python parser before, so had this turned out Sorry, didn't recognise your email-handle - not that I'm a Python Core-Dev, and pretty much ignore the "Ideas" list these days. Must have missed your previous contributions... to be a real issue, this wouldn't have been the first time. There are plenty of weird corners in Python grammar that allow unexpected programs to parse (and sometimes even run!), and these are very often connected to assignments, because, in general, assignments in Python are very elaborate and hard to describe / conceptualize about. The most popular example I've even seen used in coding interviews (which I think is a silly gimmick, but that's kind of the whole point of a lot of these interviews...) is: x = [...] for x[i] in x: print(i) Which is not an assignment by itself, but the "weirdness" results from the loop syntax sharing definitions with the "destructuring bind" style of assignment (i.e. where the left-hand side can be an arbitrary complex expression). You're right. (also about stupid 'interviewing' ideas) If someone asked me this, I'd respond by asking if that was the standard of code they work towards - and depending upon that answer would either walk-out or refer the matter to a more senior manager! In Python, everything is an object. As long as the LHS is a legal-object which makes sense for the situation, it can be used. Also, an identifier (whether x, i, or x[ i ]) should not only be considered to be its own object, but is best regarded as a pointer to some value. This is how we can have an 'immutable' tuple 'containing' a mutable list (for example) - such that elements of that list may be changed, despite being 'part of' an immutable construct! Programs are read by people. If something is a "weirdness", then chances-are it won't survive a CodeReview/a professional team's expected-standard. Not limited to Python-code! I was surprised, for example, to learn that "as" in "with_stmt" isn't shared with "as" in "except_block" (so, from the grammar perspective, these are two different keywords), and that asterisk in "except_block" isn't shared with "star_target" (also weird, since you'd think these should be the same thing). In general, and by and large, if you look at Python's grammar there are many "weird" choices that it makes to describe the language which seem counterintuitive to the programmer who tries to learn the language from examples (i.e. context-depending meaning of parenthesis, of asterisk, of period etc.) Having been exposed to this, you'd start to expect that some of this weirdness will eventually result in bugs, or at least in unexpected behavior. You're right. It is potentially confusing when the same word/symbol is used in different contexts. I've heard similar questions from learners, but not had anyone trying to mis-use something extrapolating from how the 'same' is used elsewhere. YMMV! It's the context part that's important to remember. If someone calls you "mate", that has different connotations depending upon whether you're friends, you're on a Navy ship, or in a more intimate situation - indeed there are some cultures in which the word "mate" is not used to mean 'friend' at all. Which is (more) right? Which wrong? Perhaps you're aiming for, or even used to, a more
Mtg: Object-Oriented VacExcHndlrs (UTC+13)
Let's meet on Wednesday (17Jan, 1600 NZDT (UTC+13), wearing a head-set) to talk about Object-Oriented everything. Is O-O worthwhile, or does is it just a load of guys running around and getting no-where? NB this is not a formal PUG-meeting. It's part of the "Vacation Exception Handlers" series (https://danceswithmice.info/Python/2024/VacExcHndlrs.html) - virtual-gatherings for folk left-behind to keep the wheels turning, whilst everyone else swans-off sunning themselves... (non-Kiwis please remember: it's not just school vacation, but summer-time down-under. Wish you were here?) Café-style approach, so there will be no formal presentation. All welcome. No presumption of knowledge/skill. This gathering is for everyone, from Beginner to Python-Master. Is Python an Object-Oriented language? Why does Python use (what appear to be) procedural constructs for so many of its core functions, eg len(a_list) rather than a_list.length() and sqrt(a_number) rather than a_number.sqrt()? Why do pythonista say "everything in Python is an object"? Is it faster to write in an OOP-style and/or does OOP-code run faster? If not, why bother? - insert your question here: What do you want to know? What has been bothering you about OOP (or O-O in Python) that you'd like to settle? To join us (we don't bite!), please RSVP at https://www.meetup.com/nzpug-auckland/events/298536620/ -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 12/01/24 08:53, Rich Shepard via Python-list wrote: On Thu, 11 Jan 2024, Piergiorgio Sartor via Python-list wrote: Why not to use bash script for all? Piergiorgio, That's certainly a possibility, and may well be better than python for this task. (sitting in a meeting with little to occupy my mind, whilst tidying email-InBox came back to this conversation) In the bare-description of the task, I might agree to sticking with BASH. The OP did say that the output from this will become input to a sed/mailx task! (we trust, does not involve spamming innocent folk) However, that task could also be accomplished in Python. So, unless there is an existing script (perhaps) quite why one would choose to do half in Python and half in BASH (or...) is a question. Because this is a Python forum, do the whole thing in one mode - our mode! Previous suggestions involved identifying a line by its content. Could use a neat state-transition solution. However, there is no need to consider the input-data as lines because of the concept of "white-space", well-utilised by some of Python's built-in string-functions. See code-sample, below. As mentioned before, the idea of splitting the one file (data-items related by serial-progression) and creating two quite-separate data-constructs (in this case: one holding the person's name in one file and the other the person's email-address in another) which are related 'across', ie line-by-line, is an architectural error?horror. Such would be hard to maintain, and over-time impossible to guarantee integrity. Assuming this is not a one-off exercise, see elsewhere for advice to store the captured data in some more-useful format, eg JSON, CSV, or even put into a MongoDB or RDBMS. ** code """ PythonExperiments:rich.py Demonstrate string extraction. """ __author__ = "dn, IT Consultant" __python__ = "3.12" __created__ = "PyCharm, 14 Jan 2024" __copyright__ = "Copyright © 2024~" __license__ = "GNU General Public License v3.0" # PSL import more_itertools as it DATA_FILE = "rich_data_file" READ_ONLY = "r" AS_PAIRS = 2 STRICT_PAIRING = True if __name__ == "__main__": print("\nCommencing execution\n") with open( DATA_FILE, READ_ONLY, ) as df: data = df.read() data_as_list = data.split() paired_data = it.chunked( data_as_list, AS_PAIRS, STRICT_PAIRING, ) for name, email_address in paired_data: # replace this with email-function # and/or with storage-function print( name, email_address, ) print("\nTerminating") ** sample output Calvin cal...@example.com Hobbs ho...@some.com ... ** -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 12/01/24 12:56, Chris Angelico via Python-list wrote: On Fri, 12 Jan 2024 at 08:56, Left Right via Python-list wrote: By the way, in an attempt to golf this problem, I discovered this, which seems like a parser problem: When you jump immediately to "this is a bug", all you do is make "seems"! but yes, it is a (much) less-likely explanation. yourself look like an idiot. Unsurprisingly, this is NOT a bug, this is simply that you didn't understand what was going on. The grammar isn't easy to read, and it's usually better to read the documentation instead. Those of us who studied Computer Science may well have been taught/expected to learn how to read [modified] BNF - indeed to have worked in that (cf coding in Python). Accordingly, the English text is likely easier to understand, but sometimes the BNF offers finer-detail or can be used to clarify some mis- or insufficiently-understood aspect of the text. IMHO/YMMV/etc... (Plus, golfing isn't really a goal in Python, and you didn't shorten the code by much at all. Good job.) I took my hat off to the poster, being prepared to dive-in and do this. Accordingly, was more than happy to help set him/her back onto 'the straight and narrow'. (yes it was a BNF-failing - which, credit where credit's due, I think was realised at the same time as response was typed) How many others just want us to do all their thinking for them? (there's a rude comment about wiping noses - but probably a step too far wrt the CoC) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Extract lines from file, add to new files
On 12/01/24 10:33, Left Right via Python-list wrote: By the way, in an attempt to golf this problem, I discovered this, which seems like a parser problem: This is what Python tells me about its grammar: with_stmt: | 'with' '(' ','.with_item+ ','? ')' ':' block | 'with' ','.with_item+ ':' [TYPE_COMMENT] block | ASYNC 'with' '(' ','.with_item+ ','? ')' ':' block | ASYNC 'with' ','.with_item+ ':' [TYPE_COMMENT] block with_item: | expression 'as' star_target &(',' | ')' | ':') | expression From which I figured why not something like this: with (open('example.txt', 'r'), open('emails.txt', 'w'), open('salutations.txt', 'w')) as e, m, s: for line in e: if line.strip(): (m if '@' in line else s).write(line) Which, surprise, parsers! But it seems like it's parse is wrong, because running this I get: ❯ python ./split_emails.py Traceback (most recent call last): File "/home/?/doodles/python/./split_emails.py", line 1, in with (open('example.txt', 'r'), open('emails.txt', 'w'), open('salutations.txt', 'w')) as e, m, s: TypeError: 'tuple' object does not support the context manager protocol It seems to me it shouldn't have been parsed as a tuple. The parenthesis should've been interpreted just as a decoration. NB. I'm using 3.11.6. A series of comma-separated items will be parsed as a tuple (some people think it is bounding-parentheses which define). In this case, the issue is 'connecting' the context-manager "expression" with its (as) "target". These should be more-closely paired:- with ( open( 'example.txt', 'r', ) as e, open( 'emails.txt', 'w', ) as m, open( 'salutations.txt', 'w', ) as s ): (NB code not executed here) A data-architecture of having related-data in separated serial-files is NOT recommendable! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: A problem with str VS int.
On 12/12/23 21:22, Steve GS wrote: With all these suggestions on how to fix it, no one seems to answer why it fails only when entering a two-digit number. One and three work fine when comparing with str values. It is interesting that the leading 0 on a two digit worked. Still, one digit and three digit work but not two. This is now more of a curiosity as I did use the integer comparisons. Emphasis on the word "seems"! Did you try running the code provided earlier? Did you notice that such illustrated what happens when using strings which appear as numbers, and showed how a three digit number (expressed as a string) may well precede a two- (or even a one-) digit number in the same form - and that the end-result of the sequence of integers is quite-different to the sequence of integer-values expressed as strings! Why does this happen? Because of the way data is encoded. It is language independent. The definition of order or sequence is called "collation". "Comparisons" establish relative-sequence. You will find some handy explanations of how comparisons work (eg equals or less-than) in the Python manual. After working through those three steps, if there's something that's still mystifying, please refine the question... Web.Refs: https://en.wikipedia.org/wiki/Collation https://docs.python.org/3/reference/expressions.html?highlight=comparison#value-comparisons https://docs.python.org/3/howto/sorting.html?highlight=sort -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: A problem with str VS int.
On 10/12/23 15:42, Steve GS via Python-list wrote: If I enter a one-digit input or a three-digit number, the code works but if I enter a two digit number, the if statement fails and the else condition prevails. tsReading = input(" Enter the " + Brand + " test strip reading: ") if tsReading == "": tsReading = "0" print(tsReading) if ((tsReading < "400") and (tsReading >= "0")): tsDose = GetDose(sReading) print(tsReading + "-" + tsDose) ValueFailed = False else: print("Enter valid sensor test strip Reading.") I converted the variable to int along with the if statement comparison and it works as expected. See if it fails for you... It works as expected (by Python)! This is how strings are compared - which is not the same as the apparently-equivalent numeric comparison. Think about what you expect from the code below, and then take it for a spin (of mental agility): values = [ 333, 33, 3, 222, 22, 2, 111, 11, 1, ] print( sorted( values ) ) strings = [ "333", "33", "3", "222", "22", "2", "111", "11", "1", ] print( sorted( strings ) ) The application's data appears numeric (GetDose() decides!). Accordingly, treat it so by wrapping int() or float() within a try-except (and adjusting thereafter...). "But wait, there's more!" (assuming implement as-above): if 0 <= ts_reading < 400: 1 consistent 'direction' of the comparisons = readability 2 able to "chain" the comparisons = convenience 3 identifier is PEP-008-compliant = quality and style -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: How/where to store calibration values - written by program A, read by program B
On 7/12/23 07:12, MRAB via Python-list wrote: On 2023-12-06 12:23, Thomas Passin via Python-list wrote: On 12/6/2023 6:35 AM, Barry Scott via Python-list wrote: On 6 Dec 2023, at 09:32, Chris Green via Python-list wrote: My requirement is *slightly* more complex than just key value pairs, it has one level of hierarchy, e.g.:- KEY1: a: v1 c: v3 d: v4 KEY2: a: v7 b: v5 d: v6 Different numbers of value pairs under each KEY. JSON will allow you to nest dictionaries. { 'KEY1': { 'a': v1 'c': v3 'd': v4 } 'KEY2': { 'a': v7 'b': v5 'd': v6 } } Personally I would not use .ini style these days as the format does not include type of the data. Neither does JSON. Besides, JSON is more complicated than necessary here - in fact, your example isn't even legal JSON since lines are missing commas. Fun fact - for at least some, maybe most, JSON files, using eval() on them is hugely faster than using Python's standard JSON library. I learned this when I wanted to ingest a large browser bookmarks JSON file. It wouldn't matter for a much smaller file, of course. It would be safer if you used literal_eval. Ah, memories of Python2... Does this little hack still work? What about True/False cf true/false? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
NZPUG Mtg: Making Python faster, and "Dependency Inversion"
Virtual meeting: Wednesday 6 December, 1815 for 1830 NZDT/UTC+13 Book at https://www.meetup.com/nzpug-auckland/events/295433876/ 1 Making Python faster - using type hints Tushar will lead us through: A brief history of type hints Using type checkers to verify your type hints Compiling type checked Python to make it faster Some examples of libraries and the speedups they get from type hints We'll be looking at mypy/mypyc. Audience Level: intermediate, ie understand Python constructs, functions, control flow, etc. Tushar has been a long term Python developer, OSS contributor, author and speaker. He has been working with static analysis and type checkers for the past 3 years, and has contributed to various PSF-projects such as black and mypy. 2 SOLID's Dependency Inversion Principle Olaf will complete the current Software Craftsmanship series on the SOLID Principles with a session on the Dependency Inversion Principle. This one is particularly fascinating, because at first-glance the inversion seems to be asking us to do things backwards. With understanding, we realise that it is an impressive device enabling us to focus on what is needed by the 'layer' of more valuable components, rather than the lower-level, eg UIs and external interfaces (need refresher? see https://www.bmc.com/blogs/solid-design-principles/) Audience Level: advanced, ie understand programming constructs, patterns, principles, etc. Olaf needs no introduction having generously brought us the earlier sessions in his "Software Craftsmanship" series over the last two years. Let's complete this exercise in dogged-persistence and round things off neatly - if you remember, this talk was originally scheduled last month, but technical-gremlins got in the way! Also, please tell us what topics you'd like to cover at this skill-level in future... Please come, and come with a collegial frame-of-mind. Questions and conversation will be the order of the day. If you are more confident in Python, your constructive advice, suggestions, and alternate approaches will be valued ... -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Newline (NuBe Question)
On 15/11/2023 20.25, Grizzy Adams via Python-list wrote: Hi & thanks for patience with what could be simple to you Have this (from an online "classes" tutorial) There are lots of on-line classes! --- Start Code Snippit --- students = [] grades = [] for s in geographyClass: students.append(geographyStudent(s)) for s in students: grades.append(s.school) grades.append(s.name) grades.append(s.finalGrade()) if s.finalGrade()>82: grades.append("Pass") else: grades.append("Fail") print(grades) --- End Code Snippit --- I have extended (from tutorial) it a bit, I would really like to have a newline at end of each record, I have searched (and tested) but cant get "\n" to give a newline, I get "Mydata\n" Do I need to replace "append" with "print", or is there a way to get the newline in as I append to list? Don't know how "Mydata..." results - where is it in the code. What do you see when grades is printed? Do you really want data-values all mashed together? Yes, what changed after removal of all the .append()-s, and instead, within the (second) for-loop print( school, name, ... ) was used? Is it easier to go on from there? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Clearing the Deque • Picturing Python’s `deque` data structure
You will be welcome to join us at our next (hybrid) meeting: Wednesday, 15 November 2023, 1815~2030 NZDT (0515~0730 UTC). How often do you use a deque*? “Not very” is a common answer. Perhaps you’ve never used it. In this presentation, Stephen won’t try to convince you to use it more often. Instead, he’ll present a different perspective on what this data structure is, and how it differs from a list. The presentation will compare deques and lists in a visual manner, to help us understand why we may need a deque in certain situations. We’ll also explore some demonstration examples to highlight the differences in performance between the two data structures in different scenarios. *pronounced like “deck" Audience: This presentation is ideal for those who have either never heard of deque, or have heard of it but never really used it or understood why it’s needed. The more experienced may find the visual story insightful. Stephen used to be a physicist, which is where he learned programming. After working in science and academia for over a decade, he decided to escape before it was too late. Since then, has focused exclusively on teaching coding and communicating about Python. A big part of his day is busy with running Codetoday—we teach Python coding to children between 7 and 16 years old (https://www.codetoday.co.uk/). He also runs courses for adults and corporate training programs, and particularly, writing about Python. He writes the articles he wished he had when learning. He publishes articles at The Python Coding Stack (https://thepythoncodingstack.substack.com/) and also wrote an online book (soon to be in other formats, too) for beginners, The Python Coding Book (https://thepythoncodingbook.com/). Please RSVP on Meetup.com (NZPUG Auckland Branch): https://www.meetup.com/nzpug-auckland/events/295433874/ -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: fCONV_AUSRICHTG is not defined - Why?
On 08/11/2023 06.47, Egon Frerich via Python-list wrote: I've no idea why this happens. In a module there are lists and definitions: ... ["%s%s%s " % (i[fCONV_AUSRICHTG], i[fLG2], i[fTYP]) for i in Felder]) File "/home/egon/Entw/Geldspur/geldspur/gui/GUI_Konfig.py", line 90, in ["%s%s%s " % (i[fCONV_AUSRICHTG], i[fLG2], i[fTYP]) for i in Felder]) NameError: name 'fCONV_AUSRICHTG' is not defined You see "Felder" and with "0 0 3 4" the correct value 4 for fCONV_AUSRICHTG. But there is the NameError. What does mean? Is there a change from python2 to python3? Works for me (Python 3.11 on Fedora-Linux 37) - both as a script, and simple/single import. What happens when you extract the second dimension's definitions into a module of their own, and import that (with/out less-sophisticated join)? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Safe package removal
After thread: "pip/pip3 confusion and keeping up to date" Over the years?centuries, have added various packages, using all of: - distribution-installer (dnf/yum - per apt-get) - su pip install, and - (user) pip install Because Fedora-Linux can be upgraded in-place. an amount of 'crud' hangs-about 'forever'. Accordingly, python -m pip list --outdated shows about as many entries as python - m pip list! Have (comparatively recently) standardised that projects not inside a VM or Container, will be managed by Poetry. (It's working well!) Q1 Can all (user) pip installs be safely removed, 'just like that'? Q2 How can one ascertain if system (su/sudo) pip installed packages can be removed - or are used by the op-sys/some important application? Q3 Similarly, if one can uninstall those originally installed using the distribution-installer, or if something, somewhere, will 'break'? (yes, there's an upgrade to Fedora 38 in "The Backlog") -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Checking if email is valid
On 02/11/2023 20.28, Simon Connah wrote: I'm not sure that would be practical. As I'm setting up a mailing list server I don't know if someone in the future is going to need to use one of those aliases and testing manually would be tedious. Please re-read. Discussion is about "closeness". Thus, what you might expect from email servers and Admins, NOT what you should do. That part should be quite evident by now! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Checking if email is valid
On 02/11/2023 19.56, Chris Angelico via Python-list wrote: On Thu, 2 Nov 2023 at 17:47, Simon Connah wrote: My goal is to make a simple mailing list platform. I guess I could just send email to an address and if it bounces then I can remove it from the database. Thing is I'm not sure how close to a real email address an email has to be in order to be bounced. If it was completely wrong it might just swallowed up. Every address is completely separate. There is no "closeness". Just send email to an address. Agreed. However, with names that are frequently misspelled or which are commonly-spelled slightly differently, the 'trick' is to anticipate problems and set up aliases which forward messages to the correct address*. eg Kelvin -> Kevlin Niel, Neal, Neale (etc) -> Neil (in the same way that GoodLookingGuy@mydomain -> me, or (more likely) MailAdmin -> me) * however, this can end-up perpetuating the mistake, rather than correcting... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Checking if email is valid
On 02/11/2023 19.46, Simon Connah via Python-list wrote: On Thu, 2 Nov 2023 at 05:21, Simon Connah via Python-list python-list@python.org wrote: Could someone push me in the right direction please? I just want to find out if a string is a valid email address. There is only one way to know that a string is a valid email address, and that's to send an email to it. What is your goal though? For example, if you're trying to autolink email addresses in text, you don't really care whether it's valid, only that it looks like an address. My goal is to make a simple mailing list platform. I guess I could just send email to an address and if it bounces then I can remove it from the database. Thing is I'm not sure how close to a real email address an email has to be in order to be bounced. If it was completely wrong it might just swallowed up. Exactly! Build a complementary script which inspects the returned/bounced messages, and removes those addresses. Given that the list of addresses is built from people signing-up in the first place, one has to presume that people know their own addresses and can type - there's no real defence against 'stupid'*. It's not as if you are making-up addresses yourself (in many jurisdictions it is illegal without opt-in). An email address: account@domain, has to be accurate in two ways: 1 the domain - otherwise the DNS (Domain Name System) won't be able to locate the destination email server 2 the account - otherwise the email server won't know to which mail-box the message should be delivered. The (1) is why there was some suggestion of using MX records (but may as well just send the message). The problem with (2) is that some servers will 'bounce' a message, but others will let it die silently (not wanting to add to email-spam by sending stuff 'back' if the message was spam in the first place!) The exception to (2) is a "catch-all" address, which accepts every message not addressed to a (legal) mail-box. These are sometimes used to deal with messages addressed to a staff-member who has left (for example). However, are somewhat problematic because they pick-up tons of garbage (eg earlier today I received a message to 456...@domain.tld. This is not, and never has been, a mail-box on the domain; but would drop into a catch-all mail-box. It would be an unusual MailAdmin inspecting a catch-all address, who would return a mis-addressed email to its source. If the message was addressed to s...@domain.tld, I'd be more likely to assume it was for you, and forward it to you (in the expectation that you'd fix the problem with the sender...). However, ... There are some large businesses doing what you've outlined. They have not solved this problem - and not through lack of trying! * as fast as you make something idiot-proof, the world will show you an 'improved' class of idiot! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Checking if email is valid
On 02/11/2023 00.35, Simon Connah via Python-list wrote: OK. I've been doing some reading and that you should avoid regex to check email addresses. This operation used to be a BIG THING back in the days of 'everyone' building PHP web-sites. When there were only a handful of TLDs (top-level domain names, eg the country-codes* such as .nz and .uk plus the generics such as .com and .net. Accordingly, one could hold the entire list for convenience of checking. However when IANA (the outfit responsible for the Root Zone Database and especially ICANN realised that there was money to be made, they allowed more and more TLDs. Keeping-up became a rat-race! Indeed, I've held another .info domain for twenty years, and used to suffer for my 'bleeding edge' daring - quite recently someone (who should remain name-less, and a few other less-es) sent me an email telling me how to log-in, but their log-in process wouldn't accept the 'illegal' address. Um... All together now: "a little bit of knowledge is a dangerous thing"! So what I was thinking was something like this: if type(email_recipient) != email.message.Message: I just don't know why that particular line isn't working. Will need more context. What is the objective? What is the source/pre-processing of these data-items. (etc) * Left-out .au, (a less important geo-TLD) to wind-up @Chris... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Too Broad of an exception
On 26/10/2023 04.49, rsutton via Python-list wrote: On 10/25/2023 11:06 AM, Stefan Ram wrote: r...@zedat.fu-berlin.de (Stefan Ram) writes: outer quotation marks) prints some prominent exception types. After ... "Manually removing" above was meant to be a fast first pass, where I only excluded exception types that were obviously inappropriate. It is now to be followed by a search for the appropriate exception types among those exception types left. @Rene & @Stefan, I really appreciate the guidance provided. By replacing Exception with ... It would appear that (at least one message) did not make it to email - neither to the list-archive. People wishing to learn are unable to benefit a response, if it is not sent to the list! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: return type same as class gives NameError.
On 23/10/2023 04.50, Antoon Pardon via Python-list wrote: I have the following small module: =-=-=-=-=-=-=-=-=-=-=-= 8< =-=-=-=-=-=-=-=-=-=-=-=-= from typing import NamedTuple, TypeAlias, Union from collections.abc import Sequence PNT: TypeAlias = tuple[float, float] class Pnt (NamedTuple): x: float y: float def __add__(self, other: PNT) -> Pnt: return Pnt(self[0] + other[0], self[1] + other[1]) =-=-=-=-=-=-=-=-=-=-=-= >8 =-=-=-=-=-=-=-=-=-=-=-=-= But when I import this, I get the following diagnostic: Traceback (most recent call last): File "", line 1, in File "/home/sisc/projecten/iudex/problem.py", line 10, in class Pnt (NamedTuple): File "/home/sisc/projecten/iudex/problem.py", line 14, in Pnt def __add__(self, other: PNT) -> Pnt: ^^^ NameError: name 'Pnt' is not defined. Did you mean: 'PNT'? Can someone explain what I am doing wrong? What happens when the advice is followed? Not sure why declare type-alias and then don't use it, but if insist on using class-name will be making a "forward-reference" (because class has not yet been fully defined) - see https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html#forward-references -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Where I do ask for a new feature
On 21/10/2023 01.32, Thomas Passin via Python-list wrote: On 10/19/2023 11:16 PM, Bongo Ferno via Python-list wrote: On Thursday, October 19, 2023 at 11:26:52 PM UTC-3, avi.e...@gmail.com wrote: There are many ways to make transient variables that disappear at some time and do we need yet another? Yes, you can create one of those ways but what is the big deal with deleting a variable when no longer used? Assigning a variable to something can be anything else than a temporal alias. A with statement makes clear that the alias is an alias and is local, and it automatically clears the variable after the block code is used. Python clutters the variable space with vars that are needed only on certain places, and an alias doesn't has a scope. Convenient alias are short names, and short names are limited in quantity. If the space is cluttered with short alias, it opens risks for wrong utilization. Its like writing a "for i" in a list comprehension and having to worry if "i" was already used in another place.. If a name is temporarily needed in a certain place and in a certain scope then reusing the name shouldn't be a problem. Agree. Surely, the only time we use a name like "i" is in a throw-away context? Under many circumstances Python will let us use "_" in place of a named-identifier - which enables both us and Python to remember its short-lived value/local-only use. Using an alias MERELY for the convenience of a shorter-name suggests two things: 1 lack of a competent editor/IDE, 2 lack of imagination in choosing names (perhaps one of THE skills of programming!) Yes, there are other languages which enforce a limited-scope on data-items created within or as part of a code-structure - and it IS a handy feature! On the other hand, Python's apposite stance can be useful too, eg trivial toy-example: # list_of_stuff = ... for n, element in list_of_stuff: if element == target: break # now element == target, so "element" is probably not that useful # but "n" is the index of the target-element, which may be # (there are other ways to accomplish same) Please take a look at the ideas behind "Modular Programming". This encourages the breaking-up of monolithic code and its "cluttered" global namespace, into potentially-independent code-units. The outlined-problem is solved by the independent scope of those code-units (in Python: modules, classes, functions, and "if __name__ == "__main__":". (to say nothing of the coder's virtues of "re-use", the "Single Responsibility Principle", "do one thing, and do it well", Law of Demeter, ...) Personal comment: my habit is to break specs into many classes and functions - sometimes more-so than others might prefer. Cannot recall when last had that hard-to-locate bug of unwittingly re-using a name/alias. (apologies: not a boast - a recommendation for going modular) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: type annotation vs working code
On 04/10/2023 19.41, Chris Angelico via Python-list wrote: On Wed, 4 Oct 2023 at 15:27, dn via Python-list wrote: - should the class have been called either; class SomethingSingleton(): or a Singleton() class defined, which is then sub-classed, ie class Something( Singleton ): in order to better communicate the coder's intent to the reader? TBH, I don't think it's right to have a Singleton class which is subclassed by a bunch of different singletons. They aren't really subclasses of the same class. I could imagine Singleton being a metaclass, perhaps, but otherwise, they're not really similar to each other. I'm with you on this - should have made Singleton() an ABC. Yes, would only be a skeleton around which concrete singleton classes could be built. Like you, I v.rarely use them - but which means that the ABC is useful because it would save me from having to remember the curly-bits all-over-again... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: type annotation vs working code
On 02/10/2023 00.57, Karsten Hilbert via Python-list wrote: Sorry for having conflated the core of the matter with all the Borg shenanigans, that's where I found the problem in my real code, so there :-) The first question when dealing with the Singleton Pattern is what to do when more than one instantiation is attempted: - silently return the first instance - raise an exception The 'problem' interpreting the original code was that the 'Borg Pattern', is not limited in number, but is where some class-attribute list (or dict) is used to enable all instances to be aware of each of the others (IIRC). Is choosing names as important as selecting/implementing smart algorithms? Consider this: # class Surprise: def __init__(self, with_type_annotation=False): if with_type_annotation: try: self.does_not_exist:bool print('does_not_exist does exist') except AttributeError: print('does_not_exist does not exist') return try: self.does_not_exist print('does_not_exist does exist') except AttributeError: print('does_not_exist does not exist') Surprise(with_type_annotation = False) Surprise(with_type_annotation = True) # Is this how it is supposed to be ? Wasn't this answered earlier? (@Mats) That self.does_not_exist:bool isn't interpreted by Python to mean the same as self.does_not_exist. ...and so we're addressing the important question: the try-test is for existence, cf for some value. This can also be achieved by using the attribute in a legal expression, eg: ... Might this remove the confusion (ref: @Mats): self.already_initialized:bool == True Not for me as that would _create_ already_initialized on the instance. It would not allow me to test for it. Which seems akin constructs for generating compatibility between versions. versions of ? Of the language. Sometimes one tests for existence of a given class in a module and defines said class oneself if it does not exist. But that's leading astray. What is the intent: a class where each instance is aware of every other instance - yet the word "Singleton" implies there's only one (cf a dict full of ...)? The latter. and so, returning to the matter of 'readability': - the name "Borg" de-railed comprehension - _instances:dict = {} implied the tracking of more than one - should the class have been called either; class SomethingSingleton(): or a Singleton() class defined, which is then sub-classed, ie class Something( Singleton ): in order to better communicate the coder's intent to the reader? - from there, plenty of 'templates' exist for Singletons, so why do something quite different/alien to the reader? (thus concurring with @Richard: "tricky" subverts 'readability') - is it better to use a technique which 'we' will recognise, or to ask 'us' to comprehend something 'new'? (unless the 'new' is taking-advantage of a recent extension to the language, eg switch; to justify 'trail-blazing' a new/improved/replacement 'best practice') - part of the 'tricky' seems to be an attempt to assess using an instance-attribute, rather than a class-attribute. If the :bool (or whichever) typing-annotation is added to a class-attribute (eg _instance), will the problem arise? - does the sequence _instance = False ... if not cls._instance: ie the explicit version if cls._instance == False: measure 'existence' or a value? - does the sequence _instance = None ... if not cls._instance: ie the explicit version: if cls._instance is None: measure 'existence' or identity? (indeed, are they more-or-less the same concept?) - do the *attr() functions test for 'existence'? (that said, most of the code-examples I spotted, in reading-up on this, use either None or False - et tu Brute!) Speaking of reading-up: - am wondering where PEP 661 - Sentinel Values is 'going'? - this article (https://python-patterns.guide/gang-of-four/singleton/) mentions that the original GoF Singleton Pattern preceded Python (particularly Python 3 classes). Also, that Python doesn't have complications present in C++. It further discusses "several drawbacks", which also champion 'readability' over 'trick' or 'sophistication'. I think you'll enjoy it! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: type annotation vs working code
On 01/10/2023 11.25, Karsten Hilbert via Python-list wrote: Am Sun, Oct 01, 2023 at 09:04:05AM +1300 schrieb dn via Python-list: class WorkingSingleton(Borg): def __init__(self): print(self.__class__.__name__, ':') try: self.already_initialized print('already initialized') return except AttributeError: print('initializing') self.already_initialized = True self.special_value = 42 Where's the error in my thinking (or code) ? What is your thinking? Specifically, what is the purpose of testing self.already_initialized? Apologies, my tending to use the "Socratic Method" with trainees (and avoiding any concept of personal-fault with others), means it can be difficult to tell if (personal*) introspection is being invited, or if I don't know the answer (and want to). * personal cf Python code introspection (hah!) The purpose is to check whether the singleton class has been ... initialized :-) The line self.already_initialized = True is misleading as to the fact that it doesn't matter at all what self.already_initialized is set to, as long as is exists for the next time around. Isn't it generally regarded as 'best practice' to declare (and define a value for) all attributes in __init__()? (or equivalent) In which case, it will (presumably) be defined as False; and the try-except reworded to an if-else. I fail to see how that can differentiate between first-call and subsequent call. +1 Alternately, how about using hasattr()? eg if hasattr( self.already_initialized, 'attribute_name' ): That does work. I am using that idiom in other children of Borg. But that's besides the point. I was wondering why it does not work the same way with and without the type annotation. Annotations are for describing the attribute. In Python we don't have different instructions for declaring an object and defining it, eg INTEGER COUNTER COUNTER = 0 Thus, Python conflates both into the latter, ie counter = 0 or counter:int = 0 (both have the same effect in the Python Interpreter, the latter aims to improve documentation/reading/code-checking) Typing defines (or rather labels) the object's type. Accordingly, occurs when the object is on the LHS (Left-hand Side) of an expression (which includes function-argument lists). In this 'test for existence': in the case of WorkingSingleton(), the code-line is effectively only a RHS - see 'illegal' (below). However, the annotation caused the code-line to be re-interpreted as some sort of LHS in FailingSingleton(). - as explained (@Mats) is understood as a 'typing expression' rather than 'Python code'. Apologies: fear this a rather clumsy analysis - will welcome improvement... try: self.already_initialized line is flagged by the assorted linters, etc, in my PyCharm as: Statement seems to have no effect. Well, the linter simply cannot see the purpose, which is test-of-existence. Question: is it a legal expression (without the typing)? It borders on the illegal, I suppose, as the self- introspection capabilities of the language are being leveraged to achieve a legal purpose. ...and so we're addressing the important question: the try-test is for existence, cf for some value. This can also be achieved by using the attribute in a legal expression, eg: self.already_initialized == True When introspecting code, if type-checkers cannot determine the purpose, is there likely to be a 'surprise factor' when a human reads it? (that's Socratic! I already hold an opinion: right or wrong) Might this remove the confusion (ref: @Mats): self.already_initialized:bool == True (not Socratic, don't know, haven't tested) Which seems akin constructs for generating compatibility between versions. versions of ? It seems the answer is being pointed to in Matts response. It just mightily surprised me. Me too! I am slightly confused (OK, OK!) and probably because I don't have a good handle on "Borg" beyond knowing it is a Star Wars?Trek reference (apologies to the reader sucking-in his/her breath at such an utterance!). What is the intent: a class where each instance is aware of every other instance - yet the word "Singleton" implies there's only one (cf a dict full of ...)? Second move (also, slightly) off-topic: I'm broadly in-favor of typing; additionally noting that trainees find it helpful whilst developing their code-reading skills. However, am not particularly zealous in my own code, particularly if the type-checker starts 'getting picky' with some construct and taking-up time/brain-power. (which is vitally-required for writing/testing Python code!) So, (original code-sample, second line), seeing we ended-up talking about
Re: type annotation vs working code
On 01/10/2023 08.00, Karsten Hilbert via Python-list wrote: A type annotation isn't supposed to change what code does, or so I thought: # class Borg: _instances:dict = {} def __new__(cls, *args, **kargs): # look up subclass instance cache if Borg._instances.get(cls) is None: Borg._instances[cls] = object.__new__(cls) return Borg._instances[cls] class WorkingSingleton(Borg): def __init__(self): print(self.__class__.__name__, ':') try: self.already_initialized print('already initialized') return except AttributeError: print('initializing') self.already_initialized = True self.special_value = 42 class FailingSingleton(Borg): def __init__(self): print(self.__class__.__name__, ':') try: self.already_initialized:bool print('already initialized') return except AttributeError: print('initializing') self.already_initialized = True self.special_value = 42 s = WorkingSingleton() print(s.special_value) s = FailingSingleton() print(s.special_value) # Notice how Working* and Failing differ in the type annotation of self.already_initialized only. Output: WorkingSingleton : initializing 42 FailingSingleton : already initialized <== Huh ? Traceback (most recent call last): File "/home/ncq/Projekte/gm/git/gnumed/gnumed/client/testing/test-singleton.py", line 48, in print(s.special_value) ^^^ AttributeError: 'FailingSingleton' object has no attribute 'special_value' Where's the error in my thinking (or code) ? What is your thinking? Specifically, what is the purpose of testing self.already_initialized? Isn't it generally regarded as 'best practice' to declare (and define a value for) all attributes in __init__()? (or equivalent) In which case, it will (presumably) be defined as False; and the try-except reworded to an if-else. Alternately, how about using hasattr()? eg if hasattr( self.already_initialized, 'attribute_name' ): # attribute is defined, etc As the code current stands, the: try: self.already_initialized line is flagged by the assorted linters, etc, in my PyCharm as: Statement seems to have no effect. Unresolved attribute reference 'already_initialized' for class 'WorkingSingleton'. but: self.already_initialized:bool passes without comment (see @Mats' response). Question: is it a legal expression (without the typing)? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: path to python in venv
On 28/09/2023 09.32, Jon Ribbens via Python-list wrote: On 2023-09-27, Larry Martell wrote: On Wed, Sep 27, 2023 at 12:42 PM Jon Ribbens via Python-list wrote: On 2023-09-27, Larry Martell wrote: I was under the impression that in a venv the python used would be in the venv's bin dir. But in my venvs I see this in the bin dirs: lrwxrwxrwx 1 larrymartell larrymartell7 Sep 27 11:21 python -> python3 lrwxrwxrwx 1 larrymartell larrymartell 16 Sep 27 11:21 python3 -> /usr/bin/python3 ... Not sure what this really means, nor how to get python to be in my venv. WHy do you want python to be "in your venv"? Isn't that the entire point of a venv? To have a completely self contained env? So if someone messes with the system python it will not break code running in the venv. The main point of the venv is to isolate the installed packages, rather than Python itself. I'm a bit surprised your symlinks are as shown above though - mine link from python to python3.11 to /usr/bin/python3.11, so it wouldn't change the version of python used even if I installed a different system python version. "venv — Creation of virtual environments" (https://docs.python.org/3/library/venv.html) starts by saying: «The venv module supports creating lightweight “virtual environments”, each with their own independent set of Python packages installed in their site directories.» but later expands this with: «Used to contain a specific Python interpreter...» even though the primary use-case treats the system interpreter as the "base" Python/environment. Time for some reading and proving appropriate combinations of options? Over the years there have been various proposals to enable multiple versions of Python to exist concurrently on a single machine, notably Python2 + Python3 - but am failing to recall any official docs on Python3.n + Python3.m; eg "PEP 554 – Multiple Interpreters in the Stdlib" (https://peps.python.org/pep-0554/). That said there's plenty of articles on-line (which may/not feature venv*) such as "Multiple Python interpreters" (https://developer.fedoraproject.org/tech/languages/python/multiple-pythons.html) * although the OP didn't mention an OpSys, one poster did mention Fedora-Linux... NB some of this info may be dated - it is some time since conducted this investigation (and decided not to use venv - apologies!) Am currently using PyCharm (courtesy of recent teams' conventions) and it eases both problems (which interpreter, and which development-environment/activation steps) but in automating 'the boring stuff' it will be interesting to see if in-future, I notice when the project is based upon an older system! FYI https://www.jetbrains.com/help/pycharm/installing-uninstalling-and-reloading-interpreter-paths.html (I'd be surprised if the other major tool-sets don't offer something similar) Disclaimer: JetBrains sponsor our local PUG-meetings with a door-prize. -- -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Python Launcher Pops Up When Py-based App Is Running (Mac)
On 17/09/2023 13.20, James Greenham via Python-list wrote: Hello, On the face of it, the Python-Mac mailing list is largely inactive so I'm posting here since it looks like this one is livelier. What happens when doGrab() is called from the REPL, after being 'fed' data you expect is valid? (per a unit-test) What code-level debugging has been exercised? Have you tried running the code in a debugger, in order to step into the (assumed) doGrab error? Sadly, this code is so old as to have grown whiskers. - are all the called-modules, eg webkit and the OpSys; still offering the appropriate interfaces, and continuing to behave in the expected fashion? (anything relevant in those Release Notes?) - in theory, Python 2 will still run. However, a reasonable proportion of today's Python-coders are unlikely to have ever used it. (Sunsetting Python 2 https://www.python.org/doc/sunset-python-2/) - were this code to be written using today's libraries, it is unlikely to look anything like this (which may also be contributing to the dearth of replies) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
ANN: Wed 20 Sep: Terminal-based user interfaces (TUIs) with ease using Textual
Rodrigo's back! Fresh from his successes at EuroPython... You are invited to join the next virtual NZPUG Auckland Branch meeting (Wed 20 Sep, 1830~2030 local, ie 0630~0830 UTC) Learn how to build powerful terminal-based user interfaces (TUIs) with ease using Textual - an open-source Python framework. Through this tutorial, you'll learn how to use features like Textual's built-in widgets, reactive attributes, and message-passing system, to start developing a simple TODO app that runs directly in your terminal. About Rodrigo Girão Serrão: Rodrigo has presented to NZPUG Auckland Branch previously. He speaks frequently at various PyCons (Python Conferences) and other gatherings. As well as Python, he has been playing with APL, C++, and more. Combining programming and maths, he describes himself as a mathemagician. Rodrigo has always been fascinated by problem solving and that is why he picked up programming – so that he could solve more problems. He also loves sharing knowledge, and that is why he spends so much time writing articles in his blog, writing on Twitter, and giving workshops and courses. During the week, Rodrigo can be found banging his head against the wall while trying to solve a Textual bug, as he works on Textual full-time. To RSVP (to receive the meeting-URL) and for more detail: https://www.meetup.com/nzpug-auckland/events/295433884/ The Auckland branch of the New Zealand Python Users Group meets twice monthly. You're very welcome to attend online or in-person (as available). Meeting location-details or URL will be sent to those who RSVP. We are a healthy mix of Python users. Students, academics, hobbyists, industry professionals, and many completely new to Python. The 'room' opens at 1815 (local time) with an opportunity to network with colleagues. Formal start is 1830. Aiming to finish by 2030. We are always keen to hear suggestions for meeting-topics, and to meet with folk who'd like to present or lead - eg a brief lightning talk, a practical coaching-session, a full lecture... Help is available if you've never done such a thing before! We follow the NZPUG Code of Conduct to create an inclusive and friendly environment. We express thanks to, and encourage you to investigate our sponsors: Catalyst Cloud, New Zealand Open Source Society, JetBrains, and IceHouse Ventures. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Co-op Group: Django web framework
Are you interested in learning Django? Would like to improve your Django knowledge and skills? Have you been picking-up Django piecemeal, and need to consolidate and clarify? Do you know some Django and would like to acquire mentoring and coaching skills? If so, please join us to form a Learning Django Co-op. RSVP at https://www.meetup.com/nzpug-auckland/events/295727130/ -- Regards =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Context manager for database connection
On 24/08/2023 06.11, dn via Python-list wrote: On 24/08/2023 03.41, Jason Friedman via Python-list wrote: with Database() as mydb: conn = mydb.get_connection() cursor = conn.get_cursor() cursor.execute("update table1 set x = 1 where y = 2") cursor.close() cursor = conn.get_cursor() cursor.execute("update table2 set a = 1 where b = 2") cursor.close() import jaydebeapi as jdbc class Database: database_connection = None def __init__(self, auto_commit: bool = False): self.database_connection = jdbc.connect(...) self.database_connection.jconn.setAutoCommit(auto_commit) def __enter__(self) -> jdbc.Connection: return self def __exit__(self, exception_type: Optional[Type[BaseException]], exception_value: Optional[BaseException], traceback: Optional[types.TracebackType]) -> bool: if exception_type: self.database_connection.rollback() else: self.database_connection.commit() self.database_connection.close() def get_connection(self) -> jdbc.Connection: return self.database_connection Using a context-manager is a good idea: it ensures clean-up with/without an exception occurring. Accordingly, I (and may I presume, most) like the idea when working with life-cycle type resources, eg I/O. Absolutely nothing wrong with the idea! However, the scope of a c-m is the with-block. If there are a number of 'nested operations' to be performed (which could conceivably involve other c-ms, loops, or similar code-structures) the code could become harder to read and the length of the scope unwieldy. An ease of management tactic is being able to see the start and end of a construct on the same page/screen. Such would 'limit' the length of a c-m's scope. Perhaps drawing an inappropriate parallel, but like a try-except block, there seems virtue in keeping a c-m's scope short, eg releasing resources such as a file opened for output, and some basic DBMS-es which don't offer multi-access. Accordingly, why I stopped using a c-m for database work. NB YMMV! There were two other reasons: 1 multiple databases 2 principles (and my shining virtue (?) ) 1 came across a (statistics) situation where the client was using two DBMS-es. They'd used one for some time, but then preferred another. For their own reasons, they didn't migrate old data to the new DBMS. Thus, when performing certain analyses, the data-collection part of the script might have to utilise different DB 'sources'. In at least one case, comparing data through time, the routine needed to access both DBMS-es. (oh what a tangled web we weave...) 2 another situation where the script may or may not actually have needed to access the DB. Odd? In which case, the 'expense' of the 'entry' and 'exit' phases would never be rewarded. Thus, 'inspired' to realise that had (long) been contravening SOLID's DSP advice?rule (Dependency Inversion Principle). Accordingly, these days adopt something like the following (explaining it 'backwards' to aid comprehension in case you (gentle reader) have not come-across such thinking before - remember that word, "inversion"!) - in the mainline, prior to processing, instantiate a database object database = Database( credentials ) - assume the mainline calls a function which is the substance of the script: def just_do_it( database_instance, other_args, ): while "there's work to be done": database.query( query, data, etc, ) # could be SELECT or UPDATE in and amongst the 'work' - a basic outline of query() might be: def query( self, sql, data, etc, ): cursor = self.get_cursor() cursor.execute( sql, data, ) # according to DB/connector, etc # return query results - a query can't happen without a "cursor", so either use an existing cursor, or create a fresh one: def get_cursor( self ): if not self._cursor: connection = self.get_connection() self._cursor = connection.cursor() return self._cursor NB assuming the DBMS has restrictions on cursors, I may have multiple connections with one cursor each, but in some situations it may be applicable to run multiple cursors through a single connection. - a cursor can't exist without a "connection", so either ... : def get_connection( self ): if not self._connection: self._connection = # connect to the DB return self._connection - to instantiate a DB-object in the first place, the class definition: class Database: def __init__(self): self._connection = None self._cursor = None - and the one part of the exposition that's not 'backwards': def close(self): if self._connection: self._connection.close() It might be a plan to have several query() methods,
Re: Context manager for database connection
On 24/08/2023 03.41, Jason Friedman via Python-list wrote: I want to be able to write code like this: with Database() as mydb: conn = mydb.get_connection() cursor = conn.get_cursor() cursor.execute("update table1 set x = 1 where y = 2") cursor.close() cursor = conn.get_cursor() cursor.execute("update table2 set a = 1 where b = 2") cursor.close() I'd like for both statements to succeed and commit, or if either fails to stop and for all to rollback. Is what I have below correct? import jaydebeapi as jdbc class Database: database_connection = None def __init__(self, auto_commit: bool = False): self.database_connection = jdbc.connect(...) self.database_connection.jconn.setAutoCommit(auto_commit) def __enter__(self) -> jdbc.Connection: return self def __exit__(self, exception_type: Optional[Type[BaseException]], exception_value: Optional[BaseException], traceback: Optional[types.TracebackType]) -> bool: if exception_type: self.database_connection.rollback() else: self.database_connection.commit() self.database_connection.close() def get_connection(self) -> jdbc.Connection: return self.database_connection Looking good! Assuming this is the only DB-interaction, a context-manager seems appropriate. If the real use-case calls for more interactions, the cost of establishing and breaking DB-connections becomes a consideration. Alternately, the 'length'?'life' of the context-manager *might* complicate things. Intriguing that given such a start, the code doesn't feature a context-manager for a query. That two cursors are established is also a 'cost'. Could both queries utilise the same cursor? (in which case, could consider adding to __init__() or __enter__(), and close in __exit__() ) Because the context-manager has been implemented as a class, there is no reason why one can't add more methods to that class (it doesn't need to be limited to the functional __enter__() and __exit__() methods! Indeed there is already get_connection(). Why not also a query( self, sql-code ) method? These might reduce the mainline-code to something like: if __name__ == "__main__": with Database() as mydb: mydb.query( "update table1 set x = 1 where y = 2" ) mydb.query( "update table2 set a = 1 where b = 2" ) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Imports and dot-notation
On 09/08/2023 22.30, Oliver Schinagl via Python-list wrote: ...> Looking at a python projects code and repository layout, we see the following directory structure. /project/core /project/components/module1 ... /project/components/moduleN /projects/util ...> Some modules import other modules, and I see (at the very least) two (kind of three?) different ways of doing so. `from project.components.module1 import function1, function2 as func, CONST1, CONST2 as CONST` or maybe even (which has as an advantage that it becomes clear which namespace something belongs to `from project.components.module1 import function1, function2 as module1_function2, CONST1, CONST2 as MODULE1_CONST2` but then it really just becomes personal preference, as the number of characters saved on typing is almost negative (due to having a more complex import). but also the dot notation being used `from project.components import module1` where obviously the functions are invoked as `module1.function1` etc Firstly, the path followed will depend upon the starting position! Keep reading and you should come across a reference to 'hobgoblin of little minds'. What should we be concentrating on/about? If 'naming' is a great (?the greatest) challenge of programming, surely remembering the names of classes, methods, functions, modules, etc; follows... (and by implication, as you've illustrated, perhaps where they come-from), ie code is read more often than it is written, so think about comprehension rather than typing! If one (one's team!) frequently uses a module, then a jargon may develop. For example: import numpy as np ... a = np.arange(6) In which case, those au-fait with the jargon know that the "np." prefix tells them where "arange()" can be found - conversely, that if the IDE doesn't alert, that np/numpy must be (first) import-ed. However, there is a cognitive-load to 'translate' "np" into "numpy". Not much, but then over-load is not a single thought but the combination of 'everything'. The second option (OP) is very (laboriously) clear in mapping the source of each function or constant. By way of comparison then, the code may now appear cluttered, because there's so much text to read. There would be less if an abbreviation were used. The dev.tool in-use may also influence this decision. If hovering-over an identifier reveals source-information, what value the extra code? Intelligent completion also reduces relevance of 'number of characters saved on typing'. Accordingly, give frequently-used functions/modules the abbreviation treatment -but only if YOU feel it right. Otherwise, use a longer-form to improve readability/comprehension. THE answer will thus vary by library/package/module, by application, and by coder (jargon works best if 'all' use it/understand same). Side note: Using "...import identifier, ..." does not save storage-space over "import module" (the whole module is imported regardless, IIRC), however it does form an "interface" and thus recommend leaning into the "Interface Segregation Principle", or as our InfoSec brethren would say 'the principle of least privilege'. Accordingly, prefer "from ... import ... as ...". -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Planning a Python / PyData conference
Hi Wilber, On 09/08/2023 14.28, Wilber H via Python-list wrote: Hi, I would like to plan a Python / PyData conference in the country of the Dominican Republic, and would like your feedback on how to best plan for the conference. Recommend making your request of the folks who organise EuroPython and/or PyConUS - and then same for smaller gatherings. (would suggest to ours, but those folk are already over-loaded to be ready in a few weeks' time) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Mtg ANN: Using computer vision AI to help protect the worlds rarest dolphin
Wed 16 Aug 2023, 1800~20:30 NZST (0600~0830 UTC, late-Tue in US) Details and RSVP at https://www.meetup.com/nzpug-auckland/events/295091858/ Teaching a computer to see. How computer vision is helping to protect the world’s rarest dolphin and how you can train your own model. Tane van der Boon will talk about the MAUI63 project, and then lead us through how to train and utilise a custom computer vision object detector. Essentially allowing our software to be able to see. MAUI63 was given its name because when the venture began, there were only 63 Māui dolphins left in existence. Using drone technology and AI to collect and process visual data, the founders took action to collect data to help save the world’s rarest dolphin from extinction and influence future marine conservation efforts. The MAUI63 team uses a customised drone to find and track the movement of dolphins, and enables individual dolphins to be identified through their fin markings. The information collected can then be used to inform better data driven decisions on how best to protect them. Later, Tane will lead us through a smaller task to build our own image recognizer. (more details in due course...) The Auckland Branch of the New Zealand Python Users' Group meet twice monthly. You're very welcome to attend online or in-person (as available). Meeting location-details or URL will be sent to those who RSVP. We are a healthy mix of Python users. Students, academics, hobbyists, industry professionals, and many completely new to Python. The "room" opens at 1800 (local time) with an opportunity to network with colleagues. Everything should be wrapped up by 2030. We are always keen to hear suggestions for meeting-topics, and to meet with folk who'd like to present or lead - eg a brief lightning talk, a practical coaching-session, a full lecture... Help is available if you've never done such a thing before! We follow the NZPUG Code of Conduct (https://python.nz/code-of-conduct) to create an inclusive and friendly environment. We express thanks to, and encourage you to investigate, our sponsors: Catalyst Cloud, New Zealand Open Source Society, JetBrains, and IceHouse Ventures. -- Regards =dn -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Where is the error?
On 07/08/2023 08.41, Peter J. Holzer via Python-list wrote: Mostly, error messages got a lot better in Python 3.10, but this one had me scratching my head for a few minutes. ... The error message is now a lot better, of course, but the fact that it points at the expression *before* the error completely threw me. The underlined expression is clearly not missing a comma, nor is there an error before that. My real program was a bit longer of course, so I checked the lines before that to see if I forgot to close any parentheses. Took me some time to notice the missing comma *after* the underlined expression. Is this "clairvoyant" behaviour a side-effect of the new parser or was that a deliberate decision? Found myself chuckling at this - not to be unkind, but because can easily imagine such confusion on my own part. The issue of unhelpful error messages or information aimed at a similar but different context, has been the story of our lives. Advice to trainees has always been to cast-about looking for the error - rather than taking the line-number as a precise location. Have made a note to avoid advising folk to work 'backwards'! Meantime (back at the ranch?), haven't experienced this. Using an IDE means all such stuff is reported, as one types, through highlights and squiggly lines (which should(?) be considered and cleared - before pressing the GO-button). In this case, the PyCharm* editor adds red-squiggles where the commas should have been. Hovering the cursor over a squiggle, the IDE reports "',' expected"! Its PythonConsole behaves similarly (without offering a 'hover'). Plus, even after the closing brace, it continues to assume a multi-line compound-statement (and thus won't execute, per expected REPL behavior). Way-back (grey-beard time!) when we submitted card-decks of code to be compiled over-night, one idea to avoid expensive, trivial errors/eras; was that spelling-checkers should be built-in to compilers, eg to auto-magically correct typos, eg AFF 1 TO TOTAL instead of: ADD 1 TO TOTAL These days, we can look at code from two or more years ago, 'produced' by ChatGPT (et al), aka "The Stochastic Parrot". There is some thought that artificial 'intelligence' will one-day be able to do the coding for us/predict what is required/act as a crystal ball... Speaking of which, and just because I could, here's what Chat-GPT had to say when I asked "what's wrong with ...": «The issue in the given Python code is that you're missing commas between the key-value pairs in the dictionary. Commas are required to separate different key-value pairs within a dictionary. Here's the corrected version of the code: ... » Question: If a Chat-AI is built into the IDE (I stripped such out from mine), does it take-over error reporting and diagnosis (and offer the option of replacing with its 'corrected version'?) - rather than requiring an extra copy-paste step, per above? (and need for my assumption of where the error is located) Hope you've exerted copyright over the "clairvoyant" description! * JetBrains kindly sponsor our PUG with a monthly door-prize. -- -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: isinstance()
On 05/08/2023 11.18, Chris Angelico via Python-list wrote: On Sat, 5 Aug 2023 at 09:08, dn via Python-list wrote: On 03/08/2023 11.38, Jon Ribbens via Python-list wrote: On 2023-08-02, dn wrote: Can you please explain why a multi-part second-argument must be a tuple and not any other form of collection-type? The following comment may hold a clue: if (PyTuple_Check(cls)) { /* Not a general sequence -- that opens up the road to recursion and stack overflow. */ https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684 Plus an almost total lack of demand for change I should think. Thanks for the reference! Am not proposing a change (have learned 'the rule' and accepted life-as-it-is), but was curious about the restriction: why not any (reasonable sequence)? There are quite a few places where the only option is a tuple. "spam".startswith(["sp", "h"]) Traceback (most recent call last): File "", line 1, in TypeError: startswith first arg must be str or a tuple of str, not list try: 1/0 ... except [ValueError, IndexError]: pass ... Traceback (most recent call last): File "", line 1, in ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "", line 2, in TypeError: catching classes that do not inherit from BaseException is not allowed It simplifies a lot of checks. Either it's a tuple or it's a single thing. A *lot* of values are iterable, but only tuples are tuples. As the C comment notes, this also means you don't have to worry about recursion; otherwise, even core language features like exception handling would have to iterate over a thing while ensuring that they don't get stuck in self-referential objects. (Incidentally, it seems that exception handling doesn't bother with recursion *at all*, and won't catch "(a, (b, c))" - but even if recursion is handled, it can't go infinite, short of some serious messing around in ctypes or the C API.) Yes. Thanks Chris! The idea that such 'lists' be immutable (even, hashable), and therefore a tuple, makes a certain amount of sense, and @Cameron mentioned 'frugality'. My limitation is thinking only at the Python level (which as @Jon pointed-out, is only part of the story). Faced with a situation where an argument may be a scalar-value or an iterable, I'll presume the latter, eg throw it straight into a for-loop. If that fails (because the argument is a scalar), use try-except to re-route the logic. Alternately, in an OOP situation, utilise polymorphism so that the 'scalar' and 'iterable' instances both include the appropriate method[name]. Accordingly, as long as the argument is an iterable (includes an __iter__() method), the actual type/class is more-or-less irrelevant. However, as observed earlier - and with these additions, having learned the 'rule', ie use a tuple; the brain is still pondering, but have shrugged-shoulders and carried-on regardless... -- -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: isinstance()
On 03/08/2023 11.38, Jon Ribbens via Python-list wrote: On 2023-08-02, dn wrote: Can you please explain why a multi-part second-argument must be a tuple and not any other form of collection-type? The following comment may hold a clue: if (PyTuple_Check(cls)) { /* Not a general sequence -- that opens up the road to recursion and stack overflow. */ https://github.com/python/cpython/blob/main/Objects/abstract.c#L2684 Plus an almost total lack of demand for change I should think. Thanks for the reference! Am not proposing a change (have learned 'the rule' and accepted life-as-it-is), but was curious about the restriction: why not any (reasonable sequence)? Such pondering continues in my subversive mind, given such thoughts as: - "we're all adults here" (eg frequent justification when arguing about Python not having "private attributes" per-se). So, if we introduce a complexity, on our own heads be it! (hardly likely given that all we are likely to attempt is the application of a simple and short 'list' of [un]acceptable types). NB understood that the quoted-code is applied in many and other 'scalar or tuple' situations. - Python happily enables recursion, which "opens up the road to recursion and stack overflow.". So, why install a 'nanny' to save us from ourselves here? Again: seems on-the-surface that such 'lists' (at the code-line level) will be mono-dimensional 99.9% of the time. NB having said that, the underlying mechanism *is* multi-dimensional: "direct, indirect, or virtual) subclass thereof" (https://docs.python.org/3/library/functions.html#isinstance) Further: the 'rules' say: "classinfo is a tuple of type objects (or recursively, other such tuples)". Thus, can write: >>> target_object = ... >>> inner_tuple = float, complex >>> inner_tuple (, ) >>> isinstance( target_object, ( str, inner_tuple, int, ), ) False I can't say I've ever used such construction in-the-wild - either defining and then using an "inner_tuple", or even nesting. YMMV! Any thoughts? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: How to find the full class name for a frame
On 04/08/2023 15.34, Jason Friedman via Python-list wrote: import inspect def my_example(arg1, arg2): print(inspect.stack()[0][3]) my_frame = inspect.currentframe() args,_,_,values = inspect.getargvalues(my_frame) args_rendered = [f"{x}: {values[x]}" for x in args] print(args_rendered) my_example("a", 1) The above "works" in the sense it prints what I want, namely the method name (my_example) and the arguments it was called with. The above didn't 'work' - please copy-paste and ensure that the email-client is respecting indentation. My question is: let's say I wanted to add a type hint for my_frame. my_frame: some_class_name = inspect.currentframe() What would I put for some_class_name? "frame" (without quotations) is not recognized, Nor is inspect.frame. We know Python code is executed in an execution frame. (https://docs.python.org/3/reference/executionmodel.html?highlight=frame) We are told "Frame objects Frame objects represent execution frames." (https://docs.python.org/3/reference/datamodel.html?highlight=frame). The word "represent" conflicts with the idea of "are". 'Under the hood' inspect calls sys._current_frames() (https://docs.python.org/3/library/sys.html?highlight=frame). That code is: def _getframe(*args, **kwargs): # real signature unknown """ Return a frame object from the call stack. If optional integer depth is given, return the frame object that many calls below the top of the stack. If that is deeper than the call stack, ValueError is raised. The default for depth is zero, returning the frame at the top of the call stack. This function should be used for internal and specialized purposes only. """ pass Which rather suggests that if the sys library doesn't know the signature, then neither typing nor we mere-mortals are going to do so, either. Theory: the concept of a frame does not really exist at the Python-level (remember "represents"). Frames (must) exist at the C-level (https://docs.python.org/3/c-api/frame.html?highlight=frame#c.PyFrameObject) of the virtual-machine - where typing is not a 'thing'. It's an interesting question. Perhaps a better mind than mine can give a better answer? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
isinstance()
Can you please explain why a multi-part second-argument must be a tuple and not any other form of collection-type? The signature is: isinstance(object, classinfo) leading to "classinfo" of: 1/ a single class/type, eg int 2/ a tuple of same, eg ( int, str, ) 3/ a union type, eg int | str (v3.10+) A question was asked about this at last night's PUG-meeting. The person was using the union option, but from Python v3.8. Sorting that out, he replaced the union with a list. No-go! Before correcting to a tuple... Why does the second argument need to be a tuple, given that any series of non-keyword arguments is a tuple; and that such a tuple will still need to be delimited by parentheses. In other words, other forms of delimiter/collection, eg list and set; being a series of elements/members would seem no different. Yes, the underlying C operation appears to only accept a single argument (am not C-soned, mea culpa!). There is some discussion about hashability, but isn't it coincidental rather than constructive? (again, maybe I've not understood...) Enquiring minds want to know... Web.Refs: https://docs.python.org/3/library/functions.html?highlight=isinstance#isinstance https://docs.python.org/3/c-api/object.html?highlight=isinstance#c.PyObject_IsInstance https://docs.python.org/3/reference/datamodel.html?highlight=isinstance -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Hybrid meeting ANN: Using properties and descriptors
This month's meeting (Wed 19 July, 1800 for 1830 NZST = 0600/0630 UTC) will cover more-advanced OOP Python skills. You will be most-welcome to join us... "Using properties and descriptors" will look at a series of code-examples exploring problems and how these constructs offer solutions. The presentations are in lecture-style. If there's time (or for later study), some coding workshops will be suggested. Prerequisite knowledge or experience for "Properties": Object-Oriented Programming (in Python), coding custom-classes, using available decorators, some experience in data organisation/design, PEP-008 and coding styles, and reading type-hints. Prerequisite knowledge or experience for "Descriptors": "Properties" topic in this series, coding custom-classes with 'magic methods', implementing inheritance and composition, design-experience in data organisation, Object-Oriented Design, decent understanding of OOP philosophy. Hints: A lab-/log-book will be useful for taking notes. A headset will ease asking questions, answering questions, and discussion. Python IDE ready for coding. Two choices for attendance: online or in-person (Parnell, Auckland). Please RSVP to book-in and receive access information:- - Remote attendance RSVP: https://www.meetup.com/nzpug-auckland/events/njdjssyfckbzb/ - In-person RSVP to https://www.meetup.com/nzpug-auckland/events/294745326/ You are cordially invited to join us! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: my excel file is not updated to add new data
Marc, Apologies for writing in English (the language of this Discussion List). I have attempted to keep the code in French... Thanks for this question. If it's OK with you, I would like to use it as an example-problem (and 'solution') challenge for some future Python Users' Group meeting (suitably translated, etc)... On 27/06/2023 05.46, small marcc via Python-list wrote: This code creates the path to the Excel file where the data will be written. It checks if the file already exists, and if so, reads the existing data into a DataFrame. Otherwise, it creates a new empty DataFrame. Then it concatenates the existing data with the new data and writes the result to the Excel file. Finally, it displays a message that the backup was successful and closes the information window. I do not understand why it does not work, the new data is not displayed in excel when I am in python tkinter, my data in python must be displayed in excel. I use the following code to write data to an excel file using pandas: please help meHowever, when I run this code, the new data is not showing in the excel file. I don't understand why this isn't working. Can you help me solve this problem? Is this a Python problem, or a problem with the way the solution has been coded? There are several steps in the solution-description. It is troubling (to both of us) that you are unable to locate the source of the error. Why? Because it is not noticed until the final stage "new data is not displayed"! NB am ignoring that the line defining "df" and everything thereafter, appears to be incorrectly indented - when viewed in my email-client. That said, the sequence of events seems muddled. Please review the code. Compare it to the verbal/English-language description of the solution. Can each sentence in the solution be easily identified in the code? Words like "and", "otherwise", "then", and "finally" indicate that there are multiple steps in the process. Let's split the separate sentences and phrases: - creates the path to the Excel file where the data will be written - checks if the file already exists [establish DataFrame] - if so, reads the existing data into a DataFrame - Otherwise, it creates a new empty DataFrame - concatenates the existing data with the new data - writes the result to the Excel file - displays a message that the backup was successful - closes the information window. NB addition of a task-label summarising the two DataFrame alternative situations. Now, we can outline the Python code by writing a bunch of function definitions: def create_data_path(): def check_for_file(): def establish_data_frame(): def read_existing_data(): def create_new_data_frame(): def accept_new_data(): def save_to_file(): def report(): def terminate(): NB my IDE would grumble and complain if I did this 'for real'. In a 'new code' situation, you may like to add a pass-statement inside each, and vertical-spacing to make the distracting-complaints 'go away'. Alternately and assuming the function-name doesn't say it all, add a docstring (you're going to add one anyway, right?) and expand upon the function-name with some explanation of what the function will do. In this situation, you could add the existing code. NBB the two sub-tasks have been indented here for continuity of flow. They may/may not be nested within establish_data_frame() when you detail the content of each function - not important to this outline. NBBB I've quickly drafted function-names for the sake of this discussion. I find it easier to name things when it is time to use them (in this case, call the function). Fortunately, a competent IDE will facilitate the refactoring of names ("symbols"). Yes, doing it that way costs (me) little extra effort - but it saves straining my brain up-front. That said, investing time in 'designing' a good name, will also tend to clarify and sharpen one's thinking. So, apparently I follow both paths... YMMV! Now that the solution has been outlined, one can consider what output you expect from each function, what input it will require to produce that, and the transformation in-between. For example: def create_data_path( nom_fichier ): * copy existing code into here return chemin_fichier_excel (pausing at the one function, for now...) [for non-French speakers: nom_fichier = file_name chemin_fichier_excel = data path including file-name ] How has this design-process improved things? 1 clearer thinking: we have a simple and more straightforward idea of what should happen 2 "separation of concerns": each function does one job (and should do it well!) 3 testability: we can now ensure that the (each) function performs correctly (in isolation) 4 the problem of locating the source of an error is simplified (in fact, the "testability" advantage may solve this problem - or in a new-design situation, avoid it*) Testing the function is carried-out by calling the
Re: Python Issue
On 22/06/2023 03.28, Pickle Pork via Python-list wrote: Python is unable to open. Exit Code: 1 This is not good. Please give some useful information: - from where did you download Python? - which operating system? - how do you "open" Python? etc. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Should NoneType be iterable?
On 20/06/2023 06.12, Neal Becker via Python-list wrote: On Mon, Jun 19, 2023 at 12:42 PM Chris Angelico via Python-list < python-list@python.org> wrote: On Tue, 20 Jun 2023 at 02:37, Peter Bona via Python-list wrote: Hi I am wondering if there has been any discussion why NoneType is not iterable My feeling is that it should be. Sometimes I am using API calls which return None. If there is a return value (which is iterable) I am using a for loop to iterate. Now I am getting 'TypeError: 'NoneType' object is not iterable'. (Examples are taken from here https://rollbar.com/blog/python-typeerror-nonetype-object-is-not-iterable/ ) Example 1: mylist = None for x in mylist: print(x) <== will raise TypeError: 'NoneType' object is not iterable Solution: extra If statement if mylist is not None: for x in mylist: print(x) I think Python should handle this case gracefully: if a code would iterate over None: it should not run any step. but proceed the next statement. Has this been discussed or proposed? Try this instead: for x in mylist or (): Now a None list will skip iteration entirely, allowing you to get the effect you want :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list I prefer iteration of None to be an error, as in my usage it usually indicates a mistake that I'd want to catch Agreed! A better approach is that the API return (perhaps a tuple of) both "status" and "return_value", rather than overloading the latter. That said, apparently the OP use-case is for when there is no interest in status/catch, eg where a 'nothing' answer is THE answer. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Enum + new in 3.11
On 16/06/2023 23.47, Thomas Passin via Python-list wrote: On 6/16/2023 1:40 AM, dn via Python-list wrote: Have you figured-out a use for the @enum.member and @enum.nonmember decorators (new in Python 3.11)? mypy is having trouble with 3.11 enums: "There are 83 open Enum mypy issues at the the time of this writing. Getting the Enum datatype to work with mypy is becoming impossible as I find myself having to use cast() in at least every other line." (see https://gi thub.com/python/mypy/issues/12841) There have also been other changes to enum in 3.11 - here is a useful rundown: https://www.andy-pearce.com/blog/posts/2023/Jan/whats-new-in-python-311-new-and-improved-modules/#enum I had no idea Sorry to hear about mypy. PyCharm has its own mechanism - if there's something like mypy underneath, I don't know [which]. TBH I haven't noticed any such difficulties, BUT haven't tried using more than a defined sub-class of Enum - and using such as a class. Thus: class MenuOptions( Enum ): """ Legal menu-choices. """ N = "NewGame" L = "LoadGame" if __name__ == "__main__": n:MenuOptions = MenuOptions.N print( n, type( n ) ) # MenuOptions.N works correctly, but strikes me as pedantry. (any (mypy) problematic code you'd like me to try (in PyCharm) as a comparison? Perhaps off-list - could summarise any pertinent discoveries later...) I tried messing with the enum-members, eg N:str; but realised that although this worked/was passed silently, the name of a member is not actually a string anyway. So, backed that out. Had noted the first web.ref but deemed it unimportant (to me - as above). The second I had not found, and enjoyed reading (many thanks!). «I’ll be honest, I struggled to think of concrete cases where this would be useful, since I don’t tend to pile additional functionality into my enumerations — they’re almost always just bare classes which are members of another class or module which provides the related functionality. But I think it’s good to broaden your horizons...» The last being the same view as led me to this point, and the first, the motivation for this post! As said, I tend to only use enums in a fairly mechanistic fashion. However, I have been playing-around with his "additional functionality". For example, adding the idea of a default-value if an enquiry attempts to use a 'key' which is not present (which seems 'natural', but equally goes against (my understanding of) the ethos of an enum). Next, (see earlier comment about having to invoke the @member-target as a function) was the idea that if one is using an enum as a collection of the correct choices/responses in a menu (per code snippet), making the member.value into a function* attempts to reproduce the idiom of using a dict[ionary] to simulate a case/select construct - which combines the idea of an API's constants with making a decision as to which functionality should be invoked. * function here (cf "method") because unlikely to locate such functionality within the enum. However, am also experimenting with classes (cue OOP-mumblings, eg "polymorphism", "inversion", ...) All the fun of the fair! BTW when I reach the point of making comparisons, I expect the enum will be 'cheaper' in storage; but that the dict-construct will be 'faster' - pure speculation(!) Repeating: curious cats, etc... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Enum + new in 3.11
Have you figured-out a use for the @enum.member and @enum.nonmember decorators (new in Python 3.11)? "What's New" says: Added the member() and nonmember() decorators, to ensure the decorated object is/is not converted to an enum member. The PSL docs say: @enum.member A decorator for use in enums: its target will become a member. also: enum members have names and values (the name of Color.RED is RED, the value of Color.BLUE is 3, etc.) Whereas the "Utilities and Decorators" section is slightly confusing because class decorators are mixed with others, so one has to read more-carefully. "Curiosity killed the cat" and other cautionary tales/tails... Have added the following decorated staticmethod to a basic enum. It is indeed recognised as a member of the enum, but its value is the method-object. To gain the value the method-object represents (property-like behavior) one has to call the method/enum-value as a function:- from enum import Enum, member class MenuOptions( Enum ): """ Legal menu-choices. """ N = "NewGame" L = "LoadGame" # ... @member @staticmethod def extra_member()->str: return "QuitGame" def print_demo( enum_chosen:MenuOptions )->None: """ Illustrative printing. """ print( "Name:", enum_chosen, enum_chosen.name ) if isinstance( enum_chosen, MenuOptions ): print( "Value:", enum_chosen.value ) print( MenuOptions.__members__ ) # {'N': , 'L': , 'extra_member': MenuOptions.extra_member at 0x7f0802128860>)>>} print_demo( MenuOptions[ "L" ] ) # Name: MenuOptions.L L # Value: LoadGame print_demo( MenuOptions.extra_member ) # Name: MenuOptions.extra_member extra_member # Value: 0x7f0802128860>)> print( MenuOptions.extra_member.value() ) # QuitGame Therefore, like an @property decorator applied to a method in a custom-class, it could be used to only evaluate some 'expensive' computation if/when it is needed. Similarly, it could use the other values within the enum in order to present some 'combination'. Weirdly (given that enums are considered immutable) I imagine that if the 'extra_member' were to call some external function with varying output, the value could be considered mutable when it is eventually called. Other?better ideas... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Best practice for database connection
On 01/06/2023 06.45, Thomas Passin wrote: On 5/31/2023 2:10 PM, Jason Friedman wrote: I'm trying to reconcile two best practices which seem to conflict. 1) Use a _with_ clause when connecting to a database so the connection is closed in case of premature exit. class_name = 'oracle.jdbc.OracleDriver' url = f"jdbc:oracle:thin:@//{host_name}:{port_number}/{database_name}" with jdbc.connect(class_name, url, [user_name, password], jdbc_jar_file.as_posix()) as connection: logger.info(f"Connected.") 2) Use self-made functions to streamline code. For example, there are several places I need to know if the database object is a particular type, so I create a function like this: foobar_set = set() ... def is_foobar(connection: jdbc.Connection, name: str) -> bool: """ :param connection: connection object :param name: owner.object :return: True if this object is of type foobar """ global foobar_set if not foobar_set: query = f"""select stuff from stuff""" cursor = connection.cursor() cursor.execute(query) for owner, object_name in cursor.fetchall(): foobar_set.add(f"{owner}.{object_name}") cursor.close() return name.upper() in foobar_set But that requires that I call is_foobar() with a connection object. Essentially I'd like a function that leverages the one connection I create at the beginning using a with clause. If you need to have a connection object that persists outside of the with block, then 1. you can just not use a "with" block: connection = jdbc.connect(class_name, url, [user_name, password], jdbc_jar_file.as_posix()) You will want to close the connection yourself when you are done with it. 2. do all the subsequent work within the "with" block. As with many such questions, the answer is "it depends". Sadly that's no help! Please consider: is the database critical to this application? In other words, if the script is unable to proceed without access, eg RDBMS is down or credentials are not accepted, then must the logic simply stop? Most of mine fit into that category. Accordingly, script-execution starts with setting the environment, eg gathering credentials; followed by establishing a connection to the RDBMS. An operational RDBMS is part of the environment! Now (wait for many of our colleagues to hurriedly suck in their breath) we can see that the connection is a global-value - something which resides in a base "frame" of the Python stack, and is accordingly available (R-O) 'everywhere'. NB when I say "connection", it is part of a wider RDBMS-interface object. If you wish to use a Context Manager, then its only content may be a call to main() - or preferably a function which better describes what the application will do. (per @Thomas' contribution) PS I don't like using the global keyword/command, but prefer to pass the connection as a parameter. A matter of style? A "contract": no-connection, no-query? YMMV... Another approach might be to enact the Dependency Inversion Principle (one of 'Uncle Bob' Martin's SOLID Principles. In this case, proceed with the application, and when it comes time to issue a query against the database, ask the question: "does a connection exist?". In the negative case, then call a routine which establishes the connector, passes that to the query-routine, and proceeds. Assuming multiple query-routines, the problem with this is that it takes some sleight-of-hand to create a shared connection. Alternately, maybe the application is prepared to assume the 'cost' of creating multiple connections (over time) because the RDBMS-interactions are few-and-far between, or only a small part of the total. I don't use one, but others enthuse about ORMs, eg SQLAlchemy. This suits those who combine RDBMS and OOP, and has its own persistence methodology. -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: complaint
Hi Daniel, On 31/05/2023 02.40, Daniel Ifechukwude Dibie wrote: i tried to uninstall the python 3.11.3 program from my machine so that i can re-install it is showing successful but it is ligerning on the program and features Is that word "lingering". If so, do you mean that Python did not uninstall properly - or do you mean that the reinstalled version is slow to operate? Not understanding the question, I threw it into ChatGPT:- User i tried to uninstall the python 3.11.3 program from my machine so that i can re-install it is showing successful but it is ligerning on the program and features ChatGPT If you are experiencing issues uninstalling Python 3.11.3 from your machine, here are a few steps you can try to resolve the problem: Restart your computer: Sometimes, a simple restart can help resolve issues related to the uninstallation process. Use an uninstaller tool: You can try using a third-party uninstaller tool to remove Python 3.11.3 from your system. These tools are designed to thoroughly remove programs, including any leftover files or registry entries. Some popular uninstaller tools include Revo Uninstaller, IObit Uninstaller, and Geek Uninstaller. Manual uninstallation: If the above steps don't work, you can try manually uninstalling Python 3.11.3. Here's how you can do it: Open the "Programs and Features" or "Apps & Features" section in your computer's control panel. Locate Python 3.11.3 in the list of installed programs. Click on Python 3.11.3 and select the "Uninstall" or "Remove" option. Follow the on-screen instructions to complete the uninstallation process. After the uninstallation is complete, you may also want to delete any remaining Python-related folders or files from your system. These are typically located in the "C:\Python3.11" directory. Please note that manually deleting files from your system can be risky if you're not familiar with the process. Be cautious and ensure that you're deleting the correct files associated with Python 3.11.3. Once you have successfully uninstalled Python 3.11.3, you can proceed with reinstalling it on your machine. Make sure to download the installer from the official Python website (https://www.python.org) and follow the installation instructions provided. User i tried to uninstall the python 3.11.3 program from my machine so that i can re-install it is showing successful but it is slow to load the program and features ChatGPT If the uninstallation process appears to be successful, but you are experiencing slow loading of the "Programs and Features" section in the control panel, there might be a few possible reasons for this issue. Here are some steps you can take to troubleshoot the problem: Wait for a while: Sometimes, the uninstallation process might take some time to complete all the necessary tasks, especially if it's a large program like Python. It's possible that the program is still finalizing its uninstallation in the background. Give it some time and see if the "Programs and Features" section starts responding normally after a few minutes. Restart your computer: Restarting your computer can help resolve any lingering processes or system issues that may be causing the slow loading of the "Programs and Features" section. After restarting, try accessing the control panel again and see if the problem persists. Check for other processes or services: It's possible that other processes or services running on your computer are causing a slowdown. Close any unnecessary applications and check if there are any resource-intensive processes running in the background. You can open the Task Manager (Ctrl+Shift+Esc) to check for any unusually high CPU or memory usage. Check for system errors: Run a scan for system errors using the built-in Windows System File Checker (SFC) tool. Open a Command Prompt as an administrator and run the command: sfc /scannow. This will scan your system for any corrupted or missing system files and attempt to repair them. Reinstall Python: If the issue persists, you can try reinstalling Python 3.11.3 again after performing the above steps. Make sure to follow the official installation instructions and download the installer from the official Python website (https://www.python.org). If none of the above steps resolve the slow loading issue, there might be underlying system issues causing the problem. You may consider seeking further assistance from a technical expert or your system administrator to diagnose and resolve the issue. NB I do not use MS-Windows (which is an assumption - not stated in OP), and thus cannot vouch for the veracity of this advice, nor for its accuracy - caveat emptor! Hope one of those sets of ideas will help... - will be interested to hear how you get on... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: OT: Addition of a .= operator
On 24/05/2023 12.27, Chris Angelico wrote: On Wed, 24 May 2023 at 10:12, dn via Python-list wrote: However, (continuing @Peter's theme) such confuses things when something goes wrong - was the error in the input() or in the float()? - particularly for 'beginners' - and yes, we can expand the above discussion to talk about error-handling, and repetition until satisfactory data is input by the user or (?frustration leads to) EOD... A fair consideration! Fortunately, Python has you covered. $ cat asin.py import math print( math.asin( float( input("Enter a small number: ") ) ) ) $ python3 asin.py Enter a small number: 1 1.5707963267948966 $ python3 asin.py Enter a small number: 4 Traceback (most recent call last): File "/home/rosuav/tmp/asin.py", line 4, in math.asin( ValueError: math domain error $ python3 asin.py Enter a small number: spam Traceback (most recent call last): File "/home/rosuav/tmp/asin.py", line 5, in float( ValueError: could not convert string to float: 'spam' Note that the line numbers correctly show the true cause of the problem, despite both of them being ValueErrors. So if you have to debug this sort of thing, make sure the key parts are on separate lines (even if they're all one expression, as in this example), and then the tracebacks should tell you what you need to know. Yes, an excellent example to show newcomers to make use of 'the information *provided*' - take a deep breath and read through it all, picking-out the important information... However, returning to "condense this into a single line", the frequently-seen coding is (in my experience, at least): quantity = float( input( "How many would you like? " ) ) which would not produce the helpful distinction between line-numbers/function-calls which the above (better-formatted) code does! Summarising (albeit IMHO): - if relatively trivial/likely to be well-known: collect the calls into a chain, eg user = user.strip().lower() - otherwise use separate lines in order to benefit from the stack-trace - (still saying) use separate assignments, rather than chaining more complex/lesser-known combinations - ensure that the 'final' identifier is meaningful (and perhaps the first, and/or even an 'intermediate' if pertinent or kept for re-use later) - perhaps re-use a single identifier-name as a temp-variable, if can reasonably 'get away with it' (and not confuse simple minds, like yours-truly) -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
OT: Addition of a .= operator
On 24/05/2023 10.21, Rob Cliffe via Python-list wrote: This sort of code might be better as a single expression. For example: user = ( request.GET["user"] .decode("utf-8") .strip() .lower() ) user = orm.user.get(name=user) LOL. And I thought I was the one with a (self-confessed) tendency to write too slick, dense, smart-alec code. Indeed, I was itching to shorten it (starting with the low-hanging fruit: user = user.strip().lower() ). Seriously though: this kind of condensation can come unstuck when any of the steps need to be made more complicated. ... Peter's actual code feels more Pythonic to me. (It's even 2 lines shorter! ) On 24/05/2023 09.03, Peter J. Holzer wrote: > I sometimes have a chain of transformations (e.g. first decode it, then > strip extra spaces, then normalize spelling, then look it up in a > database and replace it with the record, ...). Technically, of course > all these intermediate objects are different, and I could make that > explicit by using different variable names: > > user_param = request.GET["user"] > user_decoded = str(user_param, encoding="utf-8") > user_stripped = user_decoded.strip() > user_normalized = user_stripped.lower() > user_object = orm.user.get(name=user_normalized) > > But I find it easier to read if I just reuse the same variable name: > > user = request.GET["user"] > user = str(user, encoding="utf-8") > user = user.strip() > user = user.lower() > user = orm.user.get(name=user) > > Each instance only has a livetime of a single line (or maybe two or > three lines if I have to combine variables), so there's little risk of > confusion, and reusing the variable name makes it very clear that all > those intermediate results are gone and won't be used again. Once again/recently/another trainee came with a question about input() because he expected an number (cf input() providing a string). In this case, and to drive-home the point, preferred training illustration is: quantity_input = input( "How many would you like? " ) quantity = float( quantity_input ) Many others, and I dare so all those who suffer from the aforementioned "itch", want to condense this into a single line. However, (continuing @Peter's theme) such confuses things when something goes wrong - was the error in the input() or in the float()? - particularly for 'beginners' - and yes, we can expand the above discussion to talk about error-handling, and repetition until satisfactory data is input by the user or (?frustration leads to) EOD... Accordingly, I'd start by favoring @Peter's "explicit" approach. However (as mentioned), we end-up with a bunch of names (storage-space) which are essentially unused - and many lint-er types will deplore such single-use [like it's s-u plastic]. Thus, advice becomes somewhat the opposite(!) of function parameter handling - there, I'm happy with one or two positional-parameters, but by three-or-more, this over-taxed brain starts begging/itching for named-parameters instead. Now, the "easier" approach appeals. Indeed, if something goes wrong (per input()/float(), above), at least one has the assistance of a line-number (where error was noted). Further, using the PyCharm Debugger/pdb makes locating the design-error/coder's mistaken assumption, a snap. A debatable-point is how much we should consider more junior-level programmers. IMHO more common functions such as strip() and lower() can be combined without much loss of readability or comprehension (apart from 'function-chaining' adding complication). Whereas, the other three lines are more likely to challenge - and/or become a source of concern if mods are requested... However, some disagreement - which comes back to why the "_input" suffix (above) acts as an aide-memoire: When "user" is first used (hah!), it is the result of an http request. It is then transmogrified, until at the end where it is a query-result/object. Yes, however contrived and deliberately drawn-out the example, there is still a difference between the value which the code first produces (request/input) and that which eventually settles-out (orm/float). Accordingly (perhaps), "user_request" or "user_requested" and "user" or "user_record" (according to the way 'that' ORM operates). Perhaps more psychology rather than coding? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Addition of a .= operator
On 21/05/2023 05.54, Alex Jando wrote: I have many times had situations where I had a variable of a certain type, all I cared about it was one of it's methods. For example: import hashlib hash = hashlib.sha256(b'word') hash = hash.hexdigest() import enum class Number(enum.Enum): One: int = 1 Two: int = 2 Three: int = 3 num = Number.One num = num.value Now to be fair, in the two situations above, I could just access the method right as I declare the object, however, sometimes when passing values into functions, it's a lot messier to do that. So what I'm suggesting is something like this: import hashlib hash = hashlib.sha256(b'word') hash.=hexdigest() import enum class Number(enum.Enum): One: int = 1 Two: int = 2 Three: int = 3 num = Number.One num.=value A custom-class wrapper? Even, a decorator-able function? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Disable 'style PEP' messages
On 05/05/2023 04.28, Kevin M. Wilson via Python-list wrote: Hi... How do I set Pycharm to find only syntax errors?!! Please review response to previous message re:configuring PyCharm's helpful features towards to coders and quality-coding... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Question regarding unexpected behavior in using __enter__ method
On 21/04/2023 10.44, Lorenzo Catoni wrote: I am writing to seek your assistance in understanding an unexpected behavior that I encountered while using the __enter__ method. I have provided a code snippet below to illustrate the problem: It is expected behavior - just not what WE might have expected! class X: ... __enter__ = int ... __exit__ = lambda *_: None ... with X() as x: ... pass ... x 0 Note that what is happening is the creation of an alias for the int built-in function. The docs say: « class int(x=0) class int(x, base=10) Return an integer object constructed from a number or string x, or return 0 if no arguments are given. If x defines __int__(), int(x) returns x.__int__(). If x defines __index__(), it returns x.__index__(). If x defines __trunc__(), it returns x.__trunc__(). For floating point numbers, this truncates towards zero. ... » (https://docs.python.org/3/library/functions.html#int) No argument is given. int() delivers as-promised. Hence, the x == 0 result obtained. As you can see, the __enter__ method does not throw any exceptions and returns the output of "int()" correctly. However, one would normally expect the input parameter "self" to be passed to the function. On the other hand, when I implemented a custom function in place of the __enter__ method, I encountered the following TypeError: ``` def myint(*a, **kw): ... return int(*a, **kw) ... class X: ... __enter__ = myint ... __exit__ = lambda *_: None ... with X() as x: ... pass ... Traceback (most recent call last): File "", line 1, in File "", line 2, in myint TypeError: int() argument must be a string, a bytes-like object or a real number, not 'X' ``` Here, the TypeError occurred because "self" was passed as an input parameter to "myint". Can someone explain why this unexpected behavior occurs only in the latter case? I tested this issue on the following Python versions, and the problem persists on all of them: - Python 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0] on linux - Python 3.10.10 (main, Feb 8 2023, 14:50:01) [GCC 9.4.0] on linux - Python 3.10.7 (tags/v3.10.7:6cc6b13, Sep 5 2022, 14:08:36) [MSC v.1933 64 bit (AMD64)] on win32 I appreciate any input or insights that you might have on this matter. (you know this next part!) However, if int() is fed an X-object, which in no way represents a numeric or numeric-able value, then it crashes. After the class definition, try: int( X ) => int 0 Right-y-ho: the evidence. Firstly, what happens when int() is called with no argument? print( "int", int(), ) Note that whereas int and myint are both called with no argument(s), and therefore int() defaults to 0, myint is attempting to use the arguments as part of its return-value - "pass-through". As identified, the first argument (the a-tuple's zero-th element) is going to be x's self - which is NOT numeric, stored in a tuple - which is NOT numeric... Thus, if we "shadow" the built-in int() with a user-function, we can see what is being passed-in def int( *a, **kw, ): print( locals(), ) print( "a", a, type( a ), id( a ), ) print( len( a ), a[ 0 ], type( a[ 0 ], ) ) print( "kw", kw, type( kw ), id( kw ), ) return 42 class X: __enter__ = int __exit__ = lambda *_: None with X() as x: pass print( "After first CM", x, "\n\n") del( int ) def myint(*a, **kw): print( locals(), ) print( "a", a, type( a ), id( a ), ) print( len( a ), a[ 0 ], type( a[ 0 ], ) ) print( "kw", kw, type( kw ), id( kw ), ) return int(*a, **kw) class Y: __enter__ = myint __exit__ = lambda *_: None print( Y, type( Y ), id( Y ), ) with Y() as y: print( y, type( y ), id( y ), ) pass print( y ) => {'a': (<__main__.X object at 0x7f9b6bf13b90>,), 'kw': {}} a (<__main__.X object at 0x7f9b6bf13b90>,) 140305733882528 1 <__main__.X object at 0x7f9b6bf13b90> kw {} 140305734120576 After first CM 42 93904023389520 {'a': (<__main__.Y object at 0x7f9b6bf2c0d0>,), 'kw': {}} a (<__main__.Y object at 0x7f9b6bf2c0d0>,) 140305507712640 1 <__main__.Y object at 0x7f9b6bf2c0d0> kw {} 140305507621376 Traceback (most recent call last): File "/home/dn/Projects/analyzer/lorenzo.py", line 53, in with Y() as y: File "/home/dn/Projects/analyzer/lorenzo.py", line 44, in myint return int(*a, **kw) ^ TypeError: int() argument must be a string, a bytes-like object or a real number, not 'Y' If you remover the del() and leave my play-version of int(), Python can make it work... (the second half of the output) 94557671306576 {'a': (<__main__.Y object at 0x7f950ee2c0d0>,), 'kw': {}} a (<__main__.Y object at 0x7f950ee2c0d0>,) 140278176579200 1 <__main__.Y object at 0x7f950ee2c0d0> kw {} 140278176487936 {'a': (<__main__.Y object at 0x7f950ee2c0d0>,), 'kw': {}} a (<__main__.Y object at 0x7f950ee2c0d0>,) 140278176579152 1 <__main__.Y object at 0x7f950ee2c0d0>
Re: Pycharm IDE
On 20/04/2023 08.59, Thomas Passin wrote: On 4/19/2023 4:06 PM, Mark Bourne wrote: print(f'{LIMIT}) ^ I think this one should be: print(f'{LIMIT}') with the closing quote ;o) Yup a typo! Where's pylint when I need it? but (and you designed it this way - right?) an excellent object-lesson for the OP AND great rationale for why linters are so handy! I am bullish on F-strings, but they can stretch the typing fingers and strain the eyes. Remember the days when pythonista used to make deprecating remarks about the superiority of Python's syntax because we didn't have 'all those braces' (and other punctuation-characters) cluttering-up the code??? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: PyCharm's strict PEP and not so strict?
Try the ones which offer options to turn-on/-off particular situations (as described earlier). "stones" for bull, how do I set up the kind of "checking" I want? That's not a phrase with which I'm familiar but my guess is you need to install a linter tool and then, possibly configure it to flag or hide particular error/warning types to your personal taste. Each tool is different so you will need to read the docs on how to configure it (and how to plumb it into your IDE). Sorry, at 67 I use the idioms of many eras! "Stones", 'balls'... Let's try to dispute another old saw - the one about "old dogs"... Then there's "slowly, slowly, catchee..." (but all of these are probably regarded as 'politically incorrect', and anything disrespectful of others transgresses the Python Code of Conduct, so let's park 'the attitude' right there) @Alan is an accomplished author - even if more familiar with British slang, rather than Spanish 'translations'. This list is blessed by contributions from people from all around the globe. Accordingly, there'll be many who are unable to understand your/my aphorisms and allusions. Hence trying to stay with a more 'international English'. "When you pass through the waters, I will be with you: and when you pass through the rivers, they will not sweep over you. When you walk through the fire, you will not be burned: the flames will not set you ablaze." *Isaiah 43:2* On Wednesday, April 19, 2023 at 11:39:36 AM MDT, dn via Python-list wrote: On 20/04/2023 04.25, Alan Gauld wrote: > On 19/04/2023 10:51, Kevin M. Wilson via Python-list wrote: >> I'm in a bit of a quandary, I want some strict syntax errors to be flagged, > > OK, You might want to use a "linter" in that case because most > tools use the interpreter itself to flag syntax errors. > > >> but the use of single quotes vs double quotes! >> NOT what I need from the 'checker', you dig? > > Not really. What is the problem. Use of single versus double quotes > is straightforward - use one or the other and make sure they > match(opening and closing) You can nest one type inside the > other if you need literal quotes. And of course the same applies > to triple quotes except you can include newlines inside those. > > What kind of problems are you experiencing with quotes? > If we have some specific examples we can give specific answers. > >> "stones" for bull, how do I set up the kind of "checking" I want? > > That's not a phrase with which I'm familiar but my guess > is you need to install a linter tool and then, possibly > configure it to flag or hide particular error/warning types > to your personal taste. Each tool is different so you > will need to read the docs on how to configure it > (and how to plumb it into your IDE). > > Personally I've never felt the need for any stricter error > checking than the interpreter provides so I can't offer > anything beyond the generic suggestion to use a linter. +1 PyCharm enables a range of Python-linters. Some by add-in. Some by "External tools" (https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html). Once a linter is made-available, some allow one to tune the application or relaxation of certain 'rules', eg whether commas in a comma-separated list are to be followed by a space. Whether any enable the restriction of quotes use is another matter - probably for the reasons @Alan has already covered. PyCharm auto-magically enters both an opening-quote and a closing-quote whenever start typing a string. The 'trick' is not to delete the close whilst editing. After gaining experience, I have a convention of when to use apostrophes and when double-quotes. These old eyes dislike mixing both in a single expression - but sometimes it is the best course to follow. YMMV! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list <https://mail.python.org/mailman/listinfo/python-list> <http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=webmail> Virus-free.www.avg.com <http://www.avg.com/email-signature?utm_medium=email_source=link_campaign=sig-email_content=webmail> <#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2> -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: PyCharm's strict PEP and not so strict?
On 20/04/2023 04.25, Alan Gauld wrote: On 19/04/2023 10:51, Kevin M. Wilson via Python-list wrote: I'm in a bit of a quandary, I want some strict syntax errors to be flagged, OK, You might want to use a "linter" in that case because most tools use the interpreter itself to flag syntax errors. but the use of single quotes vs double quotes! NOT what I need from the 'checker', you dig? Not really. What is the problem. Use of single versus double quotes is straightforward - use one or the other and make sure they match(opening and closing) You can nest one type inside the other if you need literal quotes. And of course the same applies to triple quotes except you can include newlines inside those. What kind of problems are you experiencing with quotes? If we have some specific examples we can give specific answers. "stones" for bull, how do I set up the kind of "checking" I want? That's not a phrase with which I'm familiar but my guess is you need to install a linter tool and then, possibly configure it to flag or hide particular error/warning types to your personal taste. Each tool is different so you will need to read the docs on how to configure it (and how to plumb it into your IDE). Personally I've never felt the need for any stricter error checking than the interpreter provides so I can't offer anything beyond the generic suggestion to use a linter. +1 PyCharm enables a range of Python-linters. Some by add-in. Some by "External tools" (https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html). Once a linter is made-available, some allow one to tune the application or relaxation of certain 'rules', eg whether commas in a comma-separated list are to be followed by a space. Whether any enable the restriction of quotes use is another matter - probably for the reasons @Alan has already covered. PyCharm auto-magically enters both an opening-quote and a closing-quote whenever start typing a string. The 'trick' is not to delete the close whilst editing. After gaining experience, I have a convention of when to use apostrophes and when double-quotes. These old eyes dislike mixing both in a single expression - but sometimes it is the best course to follow. YMMV! -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Pycharm IDE
On 19/04/2023 21.13, Kevin M. Wilson wrote: Sorry the code snippet I sent was what is written in PyCharm. LIMIT is defined and is not causing an error! PyCharm is flagging the Parentheses at the end. It is not seeing the Parentheses as the end of the print function. def play_game(): number= random.randint(1, LIMIT) print (f'"I am thinking of a number between 1 to {LIMIT}\n") Observe... Look at the color of the parenthesis, it's green!!! !!! = WTH Same question! Please explain: why is there a (single) apostrophe? NB some email clients don't notice list communications and ReplyList - you may need to do that manually... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Pycharm IDE
Kevin, As mentioned in another response, the format of these messages seems very confused. Please copy-paste all of (the pertinent part of) the code, and ensure that the line-endings are in the correct places, tab/indentation looks correct, etc? (this will allow us to copy the same code into our PyCharm software and see what is happening!) There still appears to be both an apostrophe (') and quotation-marks ("). Do you want the user to see one/both? There was mention of this being an input prompt - hence the question-mark. Are you aware that this could be done as part of the input() function? How about creating a string and then printing that, eg prompt = f'"I am thinking of a number between 1 to {LIMIT}" print( prompt ) NB because of the question asked earlier, the above code is NOT syntactically-correct Python! NBB am assuming there's previous code which defines LIMIT On 19/04/2023 17.27, Kevin M. Wilson via Python-list wrote: Ok, I got rid of the "print (f'"I am thinking of a number between 1 to {LIMIT}\n")"print ("I am thinking of a number between 1 to {LIMIT}\n"), and Pycharm stopped complaining about it... WHY?? Perplexed "When you pass through the waters, I will be with you: and when you pass through the rivers, they will not sweep over you. When you walk through the fire, you will not be burned: the flames will not set you ablaze." Isaiah 43:2 On Tuesday, April 18, 2023 at 11:17:52 PM MDT, Kevin M. Wilson via Python-list wrote: print (f'"I am thinking of a number between 1 to {LIMIT}\n")I had the impression that the format specifier 'f' was necessary for the print function, but the double quotes are for the string printed to the user, as a prompt!The Pycharm IDE is showing that it expects a single quotation mark or ')'! No error message is displayed. Perplexed "When you pass through the waters, I will be with you: and when you pass through the rivers, they will not sweep over you. When you walk through the fire, you will not be burned: the flames will not set you ablaze." Isaiah 43:2 On Tuesday, April 18, 2023 at 06:44:37 PM MDT, aapost wrote: On 4/18/23 19:18, Kevin M. Wilson wrote: Why complain about a 'comma', or a ')'??? print (f'"I am thinking of a number between 1 to {LIMIT}\n") my version says it expects ' first (to close the fstring) then on a new line below it, it mentions the comma and ) I believe that is just showing you after ' it expects you to end the print with ) as you have or , to add additional arguments to print -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Pycharm IDE
On 19/04/2023 11.18, Kevin M. Wilson via Python-list wrote: Greetings... Kevin here:I need help, as you have guessed!I have this line: The Print Statement... Why complain about a 'comma', or a ')'???def play_game(): number = random.randint(1, LIMIT) print (f'"I am thinking of a number between 1 to {LIMIT}\n")Or is this a setting in the IDE, I need to reassign? The code is a bit difficult to read (wrapping), but the error message may be an assumption (on Python's part). Should the line be: print( F"I am thinking... ^ no extraneous/unbalanced apostrophe here? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Dataclasses, immutability(?), and ChatGPT
Are dataclasses (or instances thereof) mutable or immutable? - and in what sense? Have been experimenting with ChatGPT. In particular: its possibilities as a trainer, good ideas for methods of introducing new topics, its capability for drawing-up demonstrations or examples, its interpretation of assessment questions (ie evaluating my own work, eg do they test desired specifics, is it possible/likely to misinterpret the question, ...) Conversed with ChatGPT about the differences between (standard) custom-classes and dataclasses, and when one might prefer one over the other. We(?) started discussing how dataclasses might be introduced to trainees currently only familiar with Python's built-ins: "...how they are superior to using built-in data-constructs..." Amongst the four benefits ChatGPT listed was: « Immutable instances: By default, instances of dataclasses are immutable, which means that once created, their attributes cannot be modified. This can help to prevent unintended modifications to the data. » Huh? If we'd been discussing namedtuples over (say) dictionaries, I'd perhaps have accepted the reply. The next step was to write some code to double-check my understanding (reproduced below). No change there. (given that I'm perfect...cough, cough, splutter) Thus, back to ChatGPT to seek clarification: « You said "Immutable instances: By default, instances of dataclasses are immutable, which means that once created, their attributes cannot be modified. This can help to prevent unintended modifications to the data." The attribute-values within a data-class can be changed. In what way are Python dataclasses immutable? » ChatGPT did indeed clarify that: « You're correct that the attribute values within a dataclass can be changed, even though the instance itself is considered immutable. » That's better. The machine is as smart as I am - or I, as smart as it - or something(?) However, the supporting-explanation then appears to argue against its own clarification (and the assertion in the question): « So to clarify, when we say that instances of dataclasses are immutable, we mean that the attributes of an instance cannot be changed after it is created. In other words, if you create an instance of a dataclass, its attributes cannot be modified by any external code. If you want to change the value of an attribute, you need to create a new instance of the dataclass with the updated attribute value. ... [code excised - see below] This is because the instance is considered immutable, and its attributes cannot be changed directly. Instead, we need to create a new instance of the dataclass with the updated attribute value, like this... Now, new_person is a new instance of the Person dataclass with the updated attribute values, while the original person instance remains unchanged. So to summarize, while the attribute values within a dataclass can be changed, instances of dataclasses are considered immutable because their attributes cannot be modified directly once they are created. Any updates to the attributes require the creation of a new instance of the dataclass. » [Note] In and amongst the above explanatory-paragraphs it gives example code-snippets. Those are condensed into: >>> from dataclasses import dataclass >>> >>> @dataclass ... class Person: ... name: str ... age: int ... >>> person = Person(name='Alice', age=20) >>> >>> person.name = 'Bob' # raises AttributeError: can't set attribute >>> person.age = 21 # raises AttributeError: can't set attribute - note the erroneous comments about exceptions being raised (they weren't/aren't)! Here's a home-grown version illustrating all the points made during the investigation, by way of proof/disproof: """ PythonTraining:dataclass.py Prove/disprove claim made by Chat-GPT. """ __author__ = "dn, IT Consultant" __python__ = "3.11" __created__ = "PyCharm, 12 Apr 2023" __copyright__ = "Copyright © 2023~" __license__ = "MIT" # PSL from dataclasses import dataclass @dataclass class Coordinates(): """Sample dataclass. """ x:int y:int if __name__ == "__main__": print( "\nCommencing execution\n" ) coordinates = Coordinates( 1, 2, ) print( coordinates, id( coordinates ), ) coordinates.x = 3 print( coordinates, id( coordinates ), ) coordinates.z = 4 print( coordinates, id( coordinates ), ) print( coordinates.x, coordinates.y, coordinates.z, ) ### output: Commencing execution Coordinates(x=1, y=2) 140436963150928 Coordinates(x=3, y=2) 140436963150928 Coordinates(x=3, y=2) 140436963150928 3 2 4 Terminating ### Not only are a dataclass instance's attribute-values mutable, but further attributes can be dynamically-added to the object-instance! Yes, if the code included: coordinates = Coordinates( 5, 6, ) the new "coordinates" identifier would point to a different id() 'address', ie a fresh immutable-instance. The 'book of
Re: Initialising a Config class
On 12/04/2023 02.29, Loris Bennett wrote: Hi, Having solved my problem regarding setting up 'logger' such that it is ... My reading suggests that setting up a module with a Config class which can be imported by any part of the program might be a reasonable approach: ... However, in my config file I am using sections, so 'config' is a dict of dicts. Is there any cleverer generic way of initialising the class than ... This seems a bit clunky, because I'll end up with something like ... So the question is: How can I map a dict of dicts onto class attributes in a generic way such that only code which wants to use a new configuration parameter needs to be changed and not the Config class itself? Or should I be doing this differently? Note that the values from ConfigParser are all strings, so I am fine with the attributes being strings - I'll just convert them as needed at the point of use (but maybe there is also a better way of handling that within a class). Good progress! The first achievement has been related to the (OO) concept of "encapsulation" - collecting related data into one place. The second, has been the making of this, globally-accessible within the application. The balancing-act may now have become: making sub-sets of the data available. Thus, describing which database server and schema/view to use is part of the application's environment/config, just as much as the labels, eg company name, used in the GUI or reporting. Such data has been collected together (into a single 'source of truth'), but will be used in quite separate and/or disparate functionality within the application. The config file has been (sensibly) split into sections - when the code is dealing with the DB it does not need to be concerned with GUI-settings - or vice-versa. Accordingly, and like any other class (encapsulation), having been collected en-masse (or 'amassed', eg cmdLN options combined with a JSON/YAML/.ini file's settings) the data should be delivered appropriately. Thus, a 'getter' method (or property) to deliver the name of the company (likely a string). The one for the database may deliver a dict or key-value pairs which can be immediately 'pasted' into some db-open function-call... Such retrieval-methods will be targeted to the sub-systems of the application. They can perform formatting and coercion tasks, as necessary, eg construct full-name from two or more separate data-items, eg first_name and family_name, or perhaps providing floats where the config-collection only receives strings. (best to 'hide' all that within the class, than require the application to deal with the 'clunkiness'). Plus, they could?should provide whatever combination of data-items is appropriate to THAT part of the application's need for config-data or constraints. (etc) Stuff as much as is possible into the config class - how to collect environment-data, and satisfying any/all demands for its use. Then, the application can be relieved of all detail ("give me what I want"), only asking for whatever it requires, when it requires, and in the format it requires - tailored and ready for immediate-use... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: When is logging.getLogger(__name__) needed?
Thank you for carefully considering suggestions (and implications) - and which will 'work' for you. Further comment below (and with apologies that, unusually for me, there are many personal opinions mixed-in):- On 06/04/2023 01.06, Loris Bennett wrote: "Loris Bennett" writes: dn writes: On 01/04/2023 02.01, Loris Bennett wrote: Hi, In my top level program file, main.py, I have def main_function(): parser = argparse.ArgumentParser(description="my prog") ... args = parser.parse_args() config = configparser.ConfigParser() if args.config_file is None: config_file = DEFAULT_CONFIG_FILE else: config_file = args.config_file config.read(config_file) logging.config.fileConfig(fname=config_file) logger = logging.getLogger(__name__) do_some_stuff() my_class_instance = myprog.MyClass() def do_some_stuff(): logger.info("Doing stuff") This does not work, because 'logger' is not known in the function 'do_some_stuff'. However, if in 'my_prog/my_class.py' I have class MyClass: def __init__(self): logger.debug("created instance of MyClass") this 'just works'. I can add logger = logging.getLogger(__name__) to 'do_some_stuff', but why is this necessary in this case but not in the class? Or should I be doing this entirely differently? Yes: differently. To complement @Peter's response, two items for consideration: 1 once main_function() has completed, have it return logger and other such values/constructs. The target-identifiers on the LHS of the function-call will thus be within the global scope. 2 if the purposes of main_function() are condensed-down to a few (English, or ..., language) phrases, the word "and" will feature, eg - configure env according to cmdLN args, - establish log(s), - do_some_stuff(), ** AND ** - instantiate MyClass. If these (and do_some_stuff(), like MyClass' methods) were split into separate functions* might you find it easier to see them as separate sub-solutions? Each sub-solution would be able to contribute to the whole - the earlier ones as creating (outputting) a description, constraint, or basis; which becomes input to a later function/method. So if I want to modify the logging via the command line I might have the following: - #!/usr/bin/env python3 import argparse import logging def get_logger(log_level): """Get global logger""" logger = logging.getLogger('example') logger.setLevel(log_level) ch = logging.StreamHandler() formatter = logging.Formatter('%(levelname)s - %(message)s') ch.setFormatter(formatter) logger.addHandler(ch) return logger def do_stuff(): """Do some stuff""" #logger.info("Doing stuff!") Looks like I just need logger = logging.getLogger('example) logger.info("Doing stuff!") def main(): """Main""" parser = argparse.ArgumentParser() parser.add_argument("--log-level", dest="log_level", type=int) args = parser.parse_args() print(f"log level: {args.log_level}") logger = get_logger(args.log_level) logger.debug("Logger!") do_stuff() if __name__ == "__main__": main() - How can I get logging for 'do_stuff' in this case without explicitly passing 'logger' as an argument or using 'global'? Somehow I am failing to understand how to get 'logger' defined sufficiently high up in the program that all references 'lower down' in the program will be automatically resolved. At the risk of 'heresy', IMHO the idea of main() is (almost always) unnecessary in Python, and largely a habit carried-over from other languages (need for an entry-/end-point). NB be sure of the difference between a "script" and a "module"... My script template-overview: ''' Script docstring. ''' - author, license, etc docs global constants such as import-s set environment if __name__ == "__main__": do_this() do_that() ie the business of the script Despite its frequent use, I'm somewhat amused by the apparent duplication within: if __name__ == "__main__": main() ie if this .py file is being executed as a script, call main() - where main() is the purpose of the script. Whereas if the file is an import-ed module, do not execute any of the contained-code. Thus, the if-statement achieves the same separation as the main() function encapsulation. Also, the word main() conveys considerably less meaning than (say) establish_logging(). NB others may care to offer alternate advice for your consideration... There is a good argument for main(), in that it might enable tests to be written which assure the integration of several tasks called by the script. Plus, if one excludes non-TDD test-able code, such as user interfaces, even 'fancy headings' and
Re: [Python-Dev] Small lament...
On 04/04/2023 12.14, Guido van Rossum wrote: A bit late, this reached my inbox: https://peternorvig.medium.com/new-python-operators-9f31b56ddcc7 Did you notice that Peter Norvig's factorial-operator attempts to replace one of the very first diamond-grade provisions of [the] FLUFL? Disgraceful behavior! So disrespectful! Send him to the Spanish Inquisition... Saying that, he (Peter) lost the opportunity to promote our new dev.movement. As he pointed-out, tests are likely to give one a false sense of security with regard to the correctness of code. Accordingly, join us in the noTDD philosophy. Like NoSQL is schema-less, noTDD is scheme-less (we have NO idea what we're doing). Don't be led-astray by tests. We're all [adult-]optimists here... On Sat, Apr 1, 2023 at 11:23 AM Skip Montanaro wrote: Just wanted to throw this out there... I lament the loss of waking up on April 1st to see a creative April Fool's Day joke on one or both of these lists, often from our FLUFL... Maybe such frivolity still happens, just not in the Python ecosystem? I know you can still import "this" or "antigravity", but those are now old (both introduced before 2010). When was the last time a clever easter egg was introduced or an April Fool's Day joke played? ¯\_(ツ)_/¯ Skip ___ Python-Dev mailing list -- python-...@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-...@python.org/message/Q62W2Q6R6XMX57WK2CUGEENHMT3C3REF/ Code of Conduct: http://python.org/psf/codeofconduct/ -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Windows Gui Frontend
On 03/04/2023 02.45, Michael Torrie wrote: On 4/2/23 05:09, Dietmar Schwertberger wrote: I also did evaluate all the GUI builder from time to time between 2000 and 2016 to find one that I could recommend to colleagues, but could not find one. Then I started contributing to wxGlade and I can say that since a few years it's as easy again to build GUIs as it was with VB6. I don't want to go back to coding GUIs manually. For most use cases it's a waste of time and often it does not result in the best GUI as it's not so easy to try out and rearrange elements. But any modern GUI toolkit has sizers and layout managers. If you're manually placing elements you cannot deal with HiDPI or changing window sizes. Rearranging happens automatically when using sizers and layout managers. That said, the future of GUIs is declarative, using XAML or some other domain-specific language like QML. Examples of this include QtQuick (the long-term direction Qt is heading), and the various dot Net GUI toolkits now popular including MS' own MAUI, WPF, Avalonia. GUI designer tools (Qt Creator, Visual Studio) can be used to assist and help layout the skeleton, but ultimately the GUI is defined by code. And it works very well, is adaptive, and can automatically size and rearrange. If you want portability to mobile devices, this is where it's at. I've tried wxGlade but never could get into it, or wxWidgets in general. I used to use GTK a lot and did use Glade back then, and dynamically loaded the UI definition files at run time. Lately used more Qt with QtDesigner, and even extended Designer to support using some custom widgets I made. but the future of Qt is clearly QtQuick, so I've been learning that. Has its warts, but in general I like the declarative paradigm. It's a learning curve. Overall it's fairly powerful, flexible and portable. I have used the designer in Qt Creator a bit, but it's often faster and just as intuitive to write it in QML, since you're going to be dropping into QML frequently anyway to set properties (not unlike having to set widget properties in Qt Designer. So I guess it's 6s using the graphical designer vs straight Qt. Do the two approaches acknowledge each other and enable 'round tripping'? ie to use the best?better tool for particular jobs (and to cope with later-maintenance) can one start using one approach, switch to using the other, and then go back to the first? -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: When is logging.getLogger(__name__) needed?
On 01/04/2023 02.01, Loris Bennett wrote: Hi, In my top level program file, main.py, I have def main_function(): parser = argparse.ArgumentParser(description="my prog") ... args = parser.parse_args() config = configparser.ConfigParser() if args.config_file is None: config_file = DEFAULT_CONFIG_FILE else: config_file = args.config_file config.read(config_file) logging.config.fileConfig(fname=config_file) logger = logging.getLogger(__name__) do_some_stuff() my_class_instance = myprog.MyClass() def do_some_stuff(): logger.info("Doing stuff") This does not work, because 'logger' is not known in the function 'do_some_stuff'. However, if in 'my_prog/my_class.py' I have class MyClass: def __init__(self): logger.debug("created instance of MyClass") this 'just works'. I can add logger = logging.getLogger(__name__) to 'do_some_stuff', but why is this necessary in this case but not in the class? Or should I be doing this entirely differently? Yes: differently. To complement @Peter's response, two items for consideration: 1 once main_function() has completed, have it return logger and other such values/constructs. The target-identifiers on the LHS of the function-call will thus be within the global scope. 2 if the purposes of main_function() are condensed-down to a few (English, or ..., language) phrases, the word "and" will feature, eg - configure env according to cmdLN args, - establish log(s), - do_some_stuff(), ** AND ** - instantiate MyClass. If these (and do_some_stuff(), like MyClass' methods) were split into separate functions* might you find it easier to see them as separate sub-solutions? Each sub-solution would be able to contribute to the whole - the earlier ones as creating (outputting) a description, constraint, or basis; which becomes input to a later function/method. * there is some debate amongst developers about whether "one function, one purpose" should be a rule, a convention, or tossed in the trash. YMMV! Personal view: SOLID's "Single" principle applies: there should be only one reason (hanging over the head of each method/function, like the Sword of Damocles) for it to change - or one 'user' who could demand a change to that function. In other words, an updated cmdLN option shouldn't affect a function which establishes logging, for example. Web.Refs: https://people.engr.tamu.edu/choe/choe/courses/20fall/315/lectures/slide23-solid.pdf https://www.hanselminutes.com/145/solid-principles-with-uncle-bob-robert-c-martin https://idioms.thefreedictionary.com/sword+of+Damocles https://en.wikipedia.org/wiki/Damocles -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Python file location
On 30/03/2023 09.47, windhorn wrote: I have an older laptop I use for programming, particularly Python and Octave, running a variety of Debian Linux, and I am curious if there is a "standard" place in the file system to store this type of program file. OK, I know they should go in a repository and be managed by an IDE but this seems like way overkill for the kind of programming that I do, normally a single file. Any suggestions welcome, thanks. My home-directory has a sub-dir called Projects. Larger and identifiable projects are put in their own sub-dir of that. There are also 'buckets' which contain (usually single) files such as you describe, eg PythonTraining, NotesInClass, and the one used when folk 'here' ask code-questions: "experiments". NB "Projects" may or may not be Python-based, eg may be the name of a course, with sub-directories off that for each lecture or tutorial. Python doesn't actually care where code is placed. The act of running a script causes Python to add the script's directory to the PYTHONPATH. That means that it will 'find' any files used by/from the script, relative to that dir. Accordingly, use a dir-structure is probably more about exerting some order over what would otherwise quickly become a confusion! As you say, I see little point in making "experiments" into a repo. The life-time of any such code is that of the thread/conversation (Note to self: should clean-up some of the old-stuff in there). The others are set-up under git. That to enable the use of a GitLab instance* as a form of off-site backup, or as a means of exchange with others (at the project-level). Again, agreeing with you: if PyCharm is not running, it might not be worth (waiting while) firing it up just to check some 'experiment'. In which case, either the task can be accomplished using the Python REPL, or maybe a simple text-editor will be quite sufficient to copy-paste code from an email-message and provide a basis for the-whatever (in a file called "Allan.py", for example), and from which a suggested-solution may be posted afterwards... YMMV! * New Zealand Open Source Society perq of membership -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Standard class for time *period*?
1. Is there a standard class for a 'period', i.e. length of time specified by a start point and an end point? The start and end points could obviously be datetimes and the difference a timedelta, but the period '2022-03-01 00:00 to 2022-03-02 00:00' would be different to '2023-03-01 00:00 to 2023-03-02 00:00' even if the *duration* of both periods is the same. But even if I have a single epoch, January 2022 is obviously different to January 2023, even thought the duration might be the same. I am just surprised that there is no standard Period class, with which I could create objects and then be able to sort, check for identity, equality of length, amount of overlap, etc. I suppose people just use a datetime.datetime pair, as I have been doing so far, and tack on just the specific bit of functionality they need. The request for a "standard class" has probably been answered. Please give a use-case example to help outline the problem to be solved... eg if the Apple-picking season starts in January and runs for some weeks, and the Pear-picking season starts in February (etc), then calculation will reveal if one team of pickers can do both jobs or if two teams will be needed. If a list of tasks is to be displayed/printed, then it would be useful to list both, but in chronological order - perhaps by start-date. (this idea of possible application fails to illustrate a rationale for some of the functionality listed, above, but you get the idea of how to give us the idea...) In a custom-class, an __eq__( self, other, ) may be defined to consider any single or combination of attributes of the two classes. So, roll-your-own may not be that difficult - although anything involving time-calculations is wont to open a can-of-worms... -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list
Re: Friday finking: IDE 'macro expansions'
On 19/03/2023 01.27, 2qdxy4rzwzuui...@potatochowder.com wrote: On 2023-03-18 at 11:49:24 +, "Weatherby,Gerard" wrote: For templating, I have two Python programs for starting new work. One generates a standalone Python program with the Python shebang, a __main__ which calls def main(), and logging and argparser intialization. The other generates a pyproject.toml /setup.cfg directory structure with a main.py referenced as a console script. from setup.cfg You don't describe the process for using those programs, but if you "have two Python programs," then it sounds like you're *not* using the IDE/editor for that. (I'm not judging, I'm trying to relate your answer to dn's original question.) It is a good example of a facility or 'power' of an IDE - even if there's room for more information... The team I'm currently assisting has decided to use Poetry. PyCharm will create a new project, populating basic files, more-or-less as @George described. In the same way, if one prefers a venv (etc) instead of a Poetry structure, PyCharm will set things up similarly. Accordingly, it saves a lot of time, fiddling-about creating a bunch of (basically) empty files and sub-dirs. (that said, there a plenty of operations which have a blank-project template which can be copied-in and renamed...) Continuing the story, let's say the project calls for a PyPi-based* library, eg more_itertools, or there's a team 'standard', eg pytest; then these can be selected from a PyCharm-provided list (no need to go to PyPi to download) AND that operation will also be reflected in the pyproject.toml file. * cf one from the PSL In other words, the build file has been created and continually-maintained, by the IDE, ready for when the project is to be uploaded to a library or exported to target-machines; cf the 'tradition' of an extra, last, and not looked-forward-to, step in the process! For an opposing view, I'm much more likely to copy an old project (at the command line, often with sed) and then use my editor to morph it into a new project. IME, unless there's an imposed process, those templates and programs tend to experience bitrot, whereas going back to an old program gives me the chance to keep it up to date w.r.t. what I've learned more recently, which helps reinforce said learning. Yes... (guilty as charged!) Equally, may promulgate old habits and a lower-quality (related to the depth of learning, back-then cf 'now'). -- Regards, =dn -- https://mail.python.org/mailman/listinfo/python-list