Deutsch   English   Français   Italiano  
<mailman.10.1724704040.2917.python-list@python.org>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!fu-berlin.de!uni-berlin.de!not-for-mail
From: dn <PythonList@DancesWithMice.info>
Newsgroups: comp.lang.python
Subject: Re: Is there a better way? [combining f-string, thousands separator, 
 right align]
Date: Tue, 27 Aug 2024 08:27:11 +1200
Organization: DWM
Lines: 108
Message-ID: <mailman.10.1724704040.2917.python-list@python.org>
References: <oRHyO.142039$bV6e.134076@fx08.ams4>
 <09102d57-41cd-4428-b96f-d69e2ffe9c95@DancesWithMice.info>
 <ZsxgUBEdOsVL6c49@anomaly>
 <96f83373-c7ad-4020-96b0-51d956cf433d@DancesWithMice.info>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
X-Trace: news.uni-berlin.de f+KGKLQe8tG17VLShC1PSA8dCY160llShaZoKSnbfLPQ==
Cancel-Lock: sha1:cdfwWylqZVsQTwSqxBnaUO4ZE8c= sha256:9TY8qCkh7y2KBO8c37PQ5EsL0U2APy9DnnBGzwAh2lE=
Return-Path: <PythonList@DancesWithMice.info>
X-Original-To: python-list@python.org
Delivered-To: python-list@mail.python.org
Authentication-Results: mail.python.org; dkim=pass
 reason="2048-bit key; unprotected key"
 header.d=danceswithmice.info header.i=@danceswithmice.info
 header.b=qL7koi1b; dkim-adsp=pass; dkim-atps=neutral
X-Spam-Status: OK 0.026
X-Spam-Evidence: '*H*': 0.95; '*S*': 0.00; '(for': 0.05;
 'improvement': 0.05; ';-)': 0.07; 'correct?': 0.07; 'users,':
 0.07; '=dn': 0.09; 'admins': 0.09; 'consistency': 0.09; 'dan':
 0.09; 'environments': 0.09; 'from:addr:danceswithmice.info': 0.09;
 'from:addr:pythonlist': 0.09; 'json': 0.09; 'linux': 0.09;
 'options,': 0.09; 'received:192.168.1.64': 0.09; 'subject:, \n ':
 0.09; "they've": 0.09; '(without': 0.16; '.py': 0.16; '>>>>>':
 0.16; 'command-line': 0.16; 'compromise.': 0.16; 'explaining':
 0.16; 'form:': 0.16; 'limitations.': 0.16; 'message-
 id:@DancesWithMice.info': 0.16; 'okay,': 0.16; 'parsing': 0.16;
 'received:cloud': 0.16; 'received:rangi.cloud': 0.16; 'rpg': 0.16;
 'setuptools': 0.16; 'spot': 0.16; 'subject:align': 0.16;
 'subject:string': 0.16; 'subject:way': 0.16; 'values,': 0.16;
 'wrote:': 0.16; "can't": 0.17; "aren't": 0.19; 'libraries': 0.19;
 'to:addr:python-list': 0.20; "i've": 0.22; 'code': 0.23;
 'installed': 0.23; 'url:wiki': 0.23; 'run': 0.23; '(and': 0.25;
 'actual': 0.25; 'anyone': 0.25; 'do,': 0.26; 'programming,': 0.26;
 "isn't": 0.27; 'else': 0.27; 'old': 0.27; 'settings': 0.28; 'it,':
 0.29; 'header:User-Agent:1': 0.30; 'whole': 0.30; 'attempt': 0.31;
 'takes': 0.31; 'default': 0.31; 'putting': 0.31;
 'header:Organization:1': 0.31; '(as': 0.32; 'files,': 0.32;
 'python-list': 0.32; 'said,': 0.32; 'subject:there': 0.32;
 'received:192.168.1': 0.32; 'but': 0.32; "i'll": 0.33; 'there':
 0.33; 'windows': 0.34; 'package': 0.34; 'header:In-Reply-To:1':
 0.34; 'majority': 0.35; 'usual': 0.35; 'files': 0.36; 'fix': 0.36;
 'errors': 0.36; 'those': 0.36; 'really': 0.37; 'using': 0.37;
 'received:192.168': 0.37; 'file': 0.38; 'could': 0.38; 'changes':
 0.39; 'added': 0.39; 'valid': 0.39; 'methods': 0.39; 'still':
 0.40; 'files.': 0.40; 'want': 0.40; 'try': 0.40; 'including':
 0.60; 'skip:h 10': 0.61; 'format': 0.62; 'point.': 0.62; 'skip:z
 10': 0.62; 'here': 0.62; 'ever': 0.63; 'updates': 0.64; 'full':
 0.64; 'thus': 0.64; 'your': 0.64; 'well': 0.65; 'back': 0.67;
 'decision': 0.68; 'further': 0.69; 'azure': 0.69; 'boss': 0.69;
 'establishing': 0.69; 'took': 0.69; 'older': 0.70; 'subject:]':
 0.70; 'url-ip:208.80.154/24': 0.70; 'url-ip:208.80/16': 0.70;
 'url:wikipedia': 0.70; 'skip:f 30': 0.71; 'url-ip:208/8': 0.71;
 'longer': 0.71; 'global': 0.73; "you'll": 0.73; 'manage': 0.73;
 'costs': 0.74; 'easy': 0.74; '....': 0.76; 'clients.': 0.76;
 'proven': 0.76; 'moment': 0.81; 'adjusting': 0.84; 'apparent':
 0.84; 'realise': 0.84; 'say,': 0.84; 'thus,': 0.84; 'veritable':
 0.84; 'written,': 0.84; 'caused': 0.86; 'service,': 0.91;
 'subject:better': 0.91; "world's": 0.91; 'hole': 0.93; 'humanity':
 0.93; 'pressed': 0.93; 'skip:q 20': 0.95
DKIM-Filter: OpenDKIM Filter v2.11.0 vps.rangi.cloud 079FF68A5
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=danceswithmice.info;
 s=staff; t=1724704037;
 bh=Ojf7v2wgM3XPmO9+En6gykW6U2NoYwwHOBrJFIuQKuU=;
 h=Date:From:Subject:To:References:In-Reply-To:From;
 b=qL7koi1bf2Se0Rzb+Yjt7DTeECM/DjZgPZDlJlXaPIXmh7YOBfnjy1uaq4dGjCB/6
 kU5iQpuukqPzZm3ND+tzOHTyrRtsLOZdHtqT1TFjMcDXwqa7HDd74tT8oC4JXD2Vpx
 CvUe1qEqwKW34sXSLRO0kzTdIzF4pZ5JiK1Cup5SCT6cH1KAoX0aT7ZsD/3i+3S431
 ZEHoSb0hCt+aqLpMmTi77go6DMYEfDTz55MiLCTbzn/eR/SZlQo0xycvY0dsHb0GmW
 hcOlNhFl4XzhdX0NobpchximJiTtUXg8C+5OPICDjl5iwQTocev1+sDTg+Vv3US26k
 qJflrztntiRLw==
User-Agent: Mozilla Thunderbird
Content-Language: en-US
In-Reply-To: <ZsxgUBEdOsVL6c49@anomaly>
X-BeenThere: python-list@python.org
X-Mailman-Version: 2.1.39
Precedence: list
List-Id: General discussion list for the Python programming language
 <python-list.python.org>
List-Unsubscribe: <https://mail.python.org/mailman/options/python-list>,
 <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive: <https://mail.python.org/pipermail/python-list/>
List-Post: <mailto:python-list@python.org>
List-Help: <mailto:python-list-request@python.org?subject=help>
List-Subscribe: <https://mail.python.org/mailman/listinfo/python-list>,
 <mailto:python-list-request@python.org?subject=subscribe>
X-Mailman-Original-Message-ID: <96f83373-c7ad-4020-96b0-51d956cf433d@DancesWithMice.info>
X-Mailman-Original-References: <oRHyO.142039$bV6e.134076@fx08.ams4>
 <09102d57-41cd-4428-b96f-d69e2ffe9c95@DancesWithMice.info>
 <ZsxgUBEdOsVL6c49@anomaly>
Bytes: 9914

On 26/08/24 23:00, Dan Sommers via Python-list wrote:
> On 2024-08-26 at 20:42:32 +1200,
> dn via Python-list <python-list@python.org> wrote:
> 
>> and if we really want to go over-board:
>>
>>>>> RIGHT_JUSTIFIED = ">"
>>>>> THOUSANDS_SEPARATOR = ","
>>>>> s_format = F"{RIGHT_JUSTIFIED}{S_FIELD_WIDTH}{THOUSANDS_SEPARATOR}"
>>
>> or (better) because right-justification is the default for numbers:
>>
>>>>> s_format = F"{S_FIELD_WIDTH}{THOUSANDS_SEPARATOR}"
>>
>>
>> To the extreme that if your user keeps fiddling with presentations (none
>> ever do, do they?), all settings to do with s_format could be added to a
>> config/environment file, and thus be even further separated from
>> program-logic!
> 
> And then you'll need a parser, many of whose Unique Challenges™ aren't
> even apparent until you start parsing files from actual users, and
> you'll still need some sort of fallback in the code anyway for the case
> that s_format can't be parsed (for whatever reason).
> 
> Isn't a config file what just caused the global CrowdStrike outage?  ;-)
> 
> That said, I understand that report generators are a thing, not to
> mention RPG (https://en.wikipedia.org/wiki/IBM_RPG).
> 
> Okay, sorry; I'll just crawl back into the hole from whence I came.


Not at all. Please continue to question/ask/suggest!

This is a valid point. There are costs and benefits (trade-offs) to all 
decisions!

That said, writing one's own parser would become a veritable can of 
worms/rabbit hole. Here be dragons!

Similarly, explaining this takes longer than writing the example itself!


Older Windows users will know about .ini files, and Linux Admins are 
familiar with .conf files. Many of us are already using JSON or YAML 
formats. Any of these (and more) could be pressed into service, as 
above. At the 'top end', there are also whole libraries devoted to 
establishing application configuration or "environments": default 
values, config files, command-line options, user-input...

Have switched to using Python-poetry, which replaces packaging methods 
such as setuptools (as well as virtual-environment tools). It takes its 
project configuration specifications from a pyproject.toml file. So, for 
a few projects lately, I've been using .toml for application-config as 
well. However, I have to say, this more from an attempt at consistency 
than a decision of logic. (critique welcome)

That said, a setup.py configuration, took the form:

setup(
     name='demo_project',
     version='1.1.0',
     packages=find_packages(),
     install_requires=[
         'requests',
         'numpy',
         ...
     ],
     entry_points={
....

Accordingly, it offers an example of the simplest format (for us), and 
one which has a zero-learning pre-requisite. At execution-time, the 
moment such a config is import-ed, a syntax-error will immediately bring 
proceedings to a halt!


I have some stats-wonks as clients. They dabble in programming, but 
(fortunately) realise their limitations. (usually!) The boss has had to 
ban them from 'improving' my code ($paid to be an improvement on their 
usual quality), but including a .py configuration/options file has 
proven to be an honor-preserving compromise. Of course, they manage 
their own runs, adjusting parameters as they go. So, any errors are 
their own, and they can fix themselves (without anyone else knowing!).

Such would not work in many?most other environments - children: do not 
try this at home!


An irritation for those of us who have to delve into projects after 
they've been written, is a git-history full of the sorts of 
user-tweaking changes vilified earlier. Putting user-config into a 
separate file, even a separate sub-directory, makes it easy to spot 
which updates to ignore, and thus, which to consider!


PS the reason why CrowdStrike was not the end of humanity as we know it, 
(and only that of those who only know MSFT's eco-system) is because the 
========== REMAINDER OF ARTICLE TRUNCATED ==========