• Extract lines from file, add to new files

    From Rich Shepard@21:1/5 to All on Thu Jan 11 10:08:09 2024
    It's been several years since I've needed to write a python script so I'm asking for advice to get me started with a brief script to separate names
    and email addresses in one file into two separate files: salutation.txt and emails.txt.

    An example of the input file:

    Calvin
    calvin@example.com

    Hobbs
    hobbs@some.com

    Nancy
    nancy@herown.com

    Sluggo
    sluggo@another.com

    Having extracted salutations and addresses I'll write a bash script using
    sed and mailx to associate a message file with each name and email address.

    I'm unsure where to start given my lack of recent experience.

    TIA,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From MRAB@21:1/5 to Rich Shepard via Python-list on Thu Jan 11 18:27:31 2024
    On 2024-01-11 18:08, Rich Shepard via Python-list wrote:
    It's been several years since I've needed to write a python script so I'm asking for advice to get me started with a brief script to separate names
    and email addresses in one file into two separate files: salutation.txt and emails.txt.

    An example of the input file:

    Calvin
    calvin@example.com

    Hobbs
    hobbs@some.com

    Nancy
    nancy@herown.com

    Sluggo
    sluggo@another.com

    Having extracted salutations and addresses I'll write a bash script using
    sed and mailx to associate a message file with each name and email address.

    I'm unsure where to start given my lack of recent experience.

    From the look of it:

    1. If the line is empty, ignore it.

    2. If the line contains "@", it's an email address.

    3. Otherwise, it's a name.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Rich Shepard on Thu Jan 11 18:41:52 2024
    Rich Shepard <rshepard@appl-ecosys.com> writes:
    separate names and email addresses

    (Warning: execution of the following script will overwrite
    [DELETE!] files opened with 'w'!)

    # create source
    data = '''Calvin\ncalvin@example.com\nHobbs\nhobbs@some.com Nancy\nnancy@herown.com\nSluggo\nsluggo@another.com'''
    fn = "data20240111192219+0100"
    with open( fn, "w" )as sink: print( data, file=sink )

    # split source into two files
    with open( fn )as source: file = source.read()
    lines = file.split( '\n' )[ :-1 ]
    with open( 'salutation.txt', 'w' )as f: print( lines[ 0::2 ], file=f )
    with open( 'emails.txt', 'w' )as f: print( lines[ 1::2 ], file=f )

    # show the two result files
    with open( 'salutation.txt' )as file: print( file.read() )
    with open( 'emails.txt' )as file: print( file.read() )

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Piergiorgio Sartor@21:1/5 to Rich Shepard on Thu Jan 11 19:23:32 2024
    On 11/01/2024 19.08, Rich Shepard wrote:
    It's been several years since I've needed to write a python script so I'm asking for advice to get me started with a brief script to separate names
    and email addresses in one file into two separate files: salutation.txt and emails.txt.

    An example of the input file:

    Calvin
    calvin@example.com

    Hobbs
    hobbs@some.com

    Nancy
    nancy@herown.com

    Sluggo
    sluggo@another.com

    Having extracted salutations and addresses I'll write a bash script using
    sed and mailx to associate a message file with each name and email address.

    Why not to use bash script for all?

    bye,

    --

    piergiorgio

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to MRAB via Python-list on Thu Jan 11 10:44:23 2024
    On Thu, 11 Jan 2024, MRAB via Python-list wrote:

    From the look of it:
    1. If the line is empty, ignore it.
    2. If the line contains "@", it's an email address.
    3. Otherwise, it's a name.

    MRAB,

    Thanks. I'll take it from here.

    Regards,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mats Wichmann@21:1/5 to MRAB via Python-list on Thu Jan 11 11:45:27 2024
    On 1/11/24 11:27, MRAB via Python-list wrote:
    On 2024-01-11 18:08, Rich Shepard via Python-list wrote:
    It's been several years since I've needed to write a python script so I'm
    asking for advice to get me started with a brief script to separate names
    and email addresses in one file into two separate files:
    salutation.txt and
    emails.txt.

    An example of the input file:

    Calvin
    calvin@example.com

    Hobbs
    hobbs@some.com

    Nancy
    nancy@herown.com

    Sluggo
    sluggo@another.com

    Having extracted salutations and addresses I'll write a bash script using
    sed and mailx to associate a message file with each name and email
    address.

    I'm unsure where to start given my lack of recent experience.

    From the look of it:

    1. If the line is empty, ignore it.

    2. If the line contains "@", it's an email address.

    3. Otherwise, it's a name.


    4. Don't assume it's going to be "plain text" if the email info is
    harvested from external sources (like incoming emails) - you'll end up stumbling over a 誰かのユーザー from somewhere. Process as bytes, or be really
    careful about which encodings you allow - which for email "names" is
    something you can't actually control.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Piergiorgio Sartor via Python-list on Thu Jan 11 11:53:20 2024
    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.

    Thank you,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Mats Wichmann via Python-list on Thu Jan 11 11:22:50 2024
    On Thu, 11 Jan 2024, Mats Wichmann via Python-list wrote:

    4. Don't assume it's going to be "plain text" if the email info is
    harvested from external sources (like incoming emails) - you'll end up stumbling over a $BC/$+$N%f!<%6!<(J from somewhere. Process as bytes, or be really careful about which encodings you allow - which for email "names"
    is something you can't actually control.

    Mats,

    Not an issue for me.

    Regards,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mirko@21:1/5 to All on Thu Jan 11 21:25:26 2024
    Am 11.01.24 um 20:53 schrieb Rich Shepard via Python-list:
    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.

    Thank you,

    Rich

    awk '/@/ {print >>"emails.txt";next};NF{print >>"salutation.txt"}'
    input.txt


    SCNR ;-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to MRAB via Python-list on Thu Jan 11 13:58:07 2024
    On 1/11/2024 1:27 PM, MRAB via Python-list wrote:
    On 2024-01-11 18:08, Rich Shepard via Python-list wrote:
    It's been several years since I've needed to write a python script so I'm
    asking for advice to get me started with a brief script to separate names
    and email addresses in one file into two separate files:
    salutation.txt and
    emails.txt.

    An example of the input file:

    Calvin
    calvin@example.com

    Hobbs
    hobbs@some.com

    Nancy
    nancy@herown.com

    Sluggo
    sluggo@another.com

    Having extracted salutations and addresses I'll write a bash script using
    sed and mailx to associate a message file with each name and email
    address.

    I'm unsure where to start given my lack of recent experience.

    From the look of it:

    1. If the line is empty, ignore it.

    2. If the line contains "@", it's an email address.

    3. Otherwise, it's a name.

    You could think about a single Python script that looks through your
    input file and constructs all the message files without ever writing
    separate salutation and address files at all. Then you wouldn't need to
    write the sed and mailx scripts. It shouldn't be much harder than
    peeling out the names and addresses into separate files.

    If you haven't written any Python for some years, the preferred way to
    read and write files is using a "with" statement, like this:

    with open('email_file.txt', encoding = 'utf-8') as f:
    lines = f.readlines()
    for line in lines:
    if not line.strip(): # Skip blank lines
    continue
    # Do something with this line

    You don't need to close the file because when the "with" block ends the
    file will be closed for you.

    If the encoding is not utf-8 and you know what it will be, use that
    encoding instead.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Left Right via Python-list on Fri Jan 12 11:20:33 2024
    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 <module>
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico via Python-list on Fri Jan 12 17:34:56 2024
    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 <python-list@python.org> 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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Grizzy Adams@21:1/5 to Rich Shepard via Python-list on Fri Jan 12 06:58:50 2024
    Thursday, January 11, 2024 at 10:44, Rich Shepard via Python-list wrote:
    Re: Extract lines from file, add to (at least in part)

    On Thu, 11 Jan 2024, MRAB via Python-list wrote:

    From the look of it:
    1. If the line is empty, ignore it.
    2. If the line contains "@", it's an email address.
    3. Otherwise, it's a name.

    If that is it all? a simple Grep would do (and save on the blank line)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to AVI GROSS via Python-list on Fri Jan 12 08:39:17 2024
    On Fri, 12 Jan 2024, AVI GROSS via Python-list wrote:

    But is the solution a good one for some purpose? The two output files may
    end up being out of sync for all kinds of reasons. One of many "errors"
    can happen if multiple lines in a row do not have an "@" or a person's
    name does, for example. What if someone supplied more than one email
    address with a comma separator? This may not be expected but could cause problems.

    Avi,

    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.

    Regards,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Left Right on Sat Jan 13 12:34:07 2024
    On 13/01/24 12:11 am, Left Right wrote:
    x = [...]
    for x[i] in x: print(i)

    I suspect you've misremembered something, because this doesn't
    do anything surprising for me:

    x = [1, 2, 3]
    for x[i] in x: print(i)
    ...
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    NameError: name 'i' is not defined

    There's no destructuring going on here, just assignment to a
    sequence item.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From 2QdxY4RzWzUUiLuE@potatochowder.com@21:1/5 to Left Right via Python-list on Fri Jan 12 21:34:23 2024
    On 2024-01-13 at 02:02:39 +0100,
    Left Right via Python-list <python-list@python.org> wrote:

    Actually, after some Web search. I think, based on this: https://docs.python.org/3/reference/simple_stmts.html#grammar-token-python-grammar-augtarget
    that in Python you call this "augmented assignment target". The term
    isn't in the glossary, but so are many others.

    The Python term, at least colloquially, is "tuple unpacking."

    HTH.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From 2QdxY4RzWzUUiLuE@potatochowder.com@21:1/5 to Left Right on Sat Jan 13 06:58:34 2024
    On 2024-01-13 at 11:34:29 +0100,
    Left Right <olegsivokon@gmail.com> wrote:

    The Python term, at least colloquially, is "tuple unpacking."

    That quote is from me. Please do preserve attributions.

    Well, why use colloquialism if there's a language specification? Also,
    there weren't any tuples used in my example, at least not explicitly
    (i could've been a tuple, but that wasn't specified).

    According to the language specification,⁰ it's a "target list," and
    there can be more than one target in that list.

    The unpacking isn't really called anything, it's just the way Python
    assignment works, all the way back to its earliest stages.¹

    https://docs.python.org/3/reference/simple_stmts.html#assignment-statements,
    ¹ https://docs.python.org/release/1.4/ref/ref6.html#HDR2

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Left Right on Sun Jan 14 02:04:41 2024
    On 13/01/24 1:45 pm, Left Right wrote:

    I use the term "destructuring" in the same way Hyperspec uses it.
    It's not a Python term. I don't know what you call the same thing in
    Python. I'm not sure what you understand from it.

    I thought you meant what is usually called "unpacking" in Python. I
    don't know anything about Hyperspec, so I don't know what it means
    there.

    The fact that i was being printed inside the loop made me think
    that some deeper level of surprise was being intended, such as
    the value of i somehow getting changed by the assignment.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Chris Angelico on Sun Jan 14 02:18:00 2024
    On 13/01/24 3:14 pm, Chris Angelico wrote:
    On Sat, 13 Jan 2024 at 13:11, Left Right via Python-list <python-list@python.org> wrote:

    Very few
    languages allow arbitrary complex expressions in the same place they
    allow variable introduction.

    What do you mean by this? Most languages I've worked with allow
    variables to be initialized with arbitrary expressions, and a lot of languages allow narrowly-scoped variables.

    I think he means that in some languages the for-loop target serves as
    the declaration of a new variable, and as such has to be a bare name.

    Python isn't like that -- the target of a for-statement is treated
    exactly the same way as the lhs of an assignment. It's not scoped to the
    loop.

    BTW, the equivalent thing is valid in C too, so anyone familiar with C
    is unlikely to be surprised by this either.

    #include <stdio.h>

    int x[10];
    int i;

    int main() {
    i = 5;
    for (x[i] = 0; x[i] < 10; x[i]++)
    printf("%d\n", x[i]);
    }

    Output:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Rich Shepard via Python-list on Sun Jan 14 11:01:12 2024
    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&T 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 calvin@example.com
    Hobbs hobbs@some.com
    ...

    ******

    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Left Right via Python-list on Sun Jan 14 16:41:44 2024
    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': <<<The descriptions of lexical analysis and
    syntax use a modified Backus–Naur form (BNF) grammar notation.>>> 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 perfect and
    predictable language?


    ----

    Anyways. To the OP: I'm sorry to hijack your question. Below is the
    complete program:

    with (
    open('example.txt', 'r') as e,
    open('emails.txt', 'w') as m,
    open('salutations.txt', 'w') as s,
    ):
    for line in e:
    if line.strip():
    (m if '@' in line else s).write(line)

    Please see responses elsewhere which say why this sort of thing, whilst possible and 'easy', is not recommendable.


    it turned out to be not quite the golfing material I was hoping for.
    But, perhaps a somewhat interesting aspect of this program you don't
    see used a lot in the wild is the parenthesis in the "with" head. So,
    it's not a total write-off from the learning perspective. I.e. w/o
    looking at the grammar, and had I have this code in a coding interview question, I wouldn't be quite sure whether this code would work or
    not: one way to interpret what's going on here is to think that the expression inside parentheses is a tuple, and since tuples aren't
    context managers, it wouldn't have worked (or maybe not even parsed as
    "as" wouldn't be allowed inside tuple definition since there's no
    "universal as-expression" in Python it's hard to tell what the rules
    are). But, it turns out there's a form of "with" that has parentheses
    for decoration purposes, and that's why it parses and works to the
    desired effect.

    Again, context! All that is important 'here' is how to 'link' the file-descriptor with an identifier. Similarly, whilst we could write:

    a, b, c = 1, 2, 3

    (and BTW that is legal Python - for anyone seeing such for the first time)
    and whilst it is shorter (and I've been known to write such), the need
    to read carefully in order to pair-up the relative positions make it
    less readable than

    a = 1; b = 2; c = 3

    (and some would argue, quite reasonably, that it would be better were
    they on separate lines)

    Similarly, many dev.teams have a 'standard' which suggests that once a function/method has three or more arguments, relative-positioning should
    go out-the-window, in favor of named-arguments. This speeds
    comprehension and reduces errors.

    In the original mental-model, the difficulty was which file-descriptor
    would be paired with which file (previously described). The multiple
    as-s make it more readable and more comprehensible.


    Since it looks like you are doing this for educational reasons, I
    think there's a tiny bit of value to my effort.

    That's what we're (all) here for!
    (and not forgetting that the OP described a skill-level well below that
    of most of this post and your question, which enabled (and deserved,
    IMHO) appropriate respect).

    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico via Python-list on Mon Jan 15 11:29:02 2024
    On 15/01/24 10:23, Chris Angelico via Python-list wrote:
    On Mon, 15 Jan 2024 at 08:15, Left Right <olegsivokon@gmail.com> 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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico on Mon Jan 15 11:30:03 2024
    On 14/01/24 16:48, Chris Angelico wrote:
    On Sun, 14 Jan 2024 at 14:43, dn via Python-list <python-list@python.org> 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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to All on Mon Jan 15 14:01:07 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Left Right on Mon Jan 15 13:54:16 2024
    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 'pretense', in the same way
    that when 'the kids' use phrases like "yeah, nah" which are totally
    devoid of logical-meaning, I can deduce the attitude behind their utterance.

    So, again, yes I think you're right about what appears in the docs - why
    change it if we can accept that what was there before can still be
    applied today? Again, a comfort for those who've been-around, but
    perhaps failing to take into account others. (?)

    Recently we 'lost' Niklaus Wirth. I recall the days when he was part of
    teams looking at languages. Back then we contemplated improvements to
    COBOL, FORTRAN, even PL/1 (an attempt said to take the 'best' of the
    previous two - but the scuttlebutt suggested its result was the
    opposite), ALGOL68, and the idea of a new language for the world's
    largest user of computers: Ada. We devoured new drafts of future
    standards; but they were thick tomes. Soon after, Wirth simplified
    rather than expanded, and developed Pascal. 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'.
    Even-so, lessons were learned from Pascal, and its development path, and
    thus Oberon is 'same but different'. Things change. We learn (and
    improve - hopefully). etc, etc...


    As mentioned, the value of this discussion would be better realised on
    the Python-Ideas Discussion List or amongst the Core-Devs - and there is
    a Python Docs Team, if you'd prefer to contribute at that level.


    Back to the point that has been made, repeatedly: relying upon a single
    source is not likely to be helpful. We've been talking about 'rules',
    let's expand that out to "laws". I am unaware of a jurisdiction which
    relies totally upon written legislation. Every legal system brings those
    into the real-world with interpretation and "case law" or "the law of precedent". Often, the latter ends-up contorting or stretching the
    former in ways the original authors did not (even, could not) imagine.

    Life, the universe, and everything!


    Yes it is hard to read - and even harder to learn-from;

    This wasn't my point. My point is that it's hard to learn languages
    that are "one off" in the group languages that all share a similar set
    of rules. The difficulty comes from the surprise caused by the unique
    use, not because there's something inherently difficult about reading
    grammar languages. In fact, however you look at Python's grammar
    language, in a sense, it's a lot easier to read than Python itself
    because it has significantly fewer rules. Of course, the number of
    rules doesn't entirely capture the difficulty, but it's a useful
    metric.

    Rules? What rules?

    Each (programming) language was originally developed with specific
    objectives in-mind. Usually the history would include determinations to
    avoid certain aspects of other/existing languages.

    As long as that objective includes 'pushing the envelope' or 'making
    things better'; any 'rules' must bend or break in-concert.


    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.

    This is a very interesting statement... I don't think you are fully
    aware of what it might mean :) Here are just a few questions for you
    to ponder:

    * What is Python? Is it only Python 3.12? Is Python 3.11 not Python?
    How far back do you go to draw the line?
    * What makes something an "object"? Is it the ability to dispatch on?
    Is it the inheritance from "object" type?
    * What elements of the language do you consider part of the language
    that can be included in your "all" set. Do types belong in that set?
    Do expressions belong in that set? What about comments?

    Topic addressed elsewhere.

    Yet, here we are discussing a Python 'eco-system', which consists of
    numbers of parts. That those parts do, or do not, integrate as tidily or elegantly as we might like, is a fact of life (also previously discussed).

    What language might fulfill these exacting criteria?
    - and if that exists, what are you doing here?


    Depending on how you answer these questions, you'd have some further
    problems to deal with. For example, historically, Python had plenty
    of things that didn't inherit from "object" but acted similar to one.
    I believe "module" objects were among the last to transition into
    object inheritance lane, which might have happened some time around
    Python 3.5. Of course, there are plenty of things that are "in
    Python", at least due to its grammar, that are hard to describe as
    objects (eg. comments). So, you'd have to make a special subset of
    Python language that (eg. excludes comments) to claim that everything
    is an object.

    Most importantly, however, regardless of what you understand to be an
    object, or how you decide to answer any of those questions: what value
    does such a claim possibly have? Especially, given the context...

    Intriguing. I laughed when I first saw Python's docstrings (one type of "comment") because it was obvious (to me) that they were being treated
    as strings. The fact that they were not identified ("assigned" or
    "bound", if you prefer) is neither here-nor-there.
    (just as, on the RHS, all Python-functions return a value, even if it is
    None - which is not obvious to many, at-first)

    Admittedly, a #-comment does not qualify as an object; but then the hash
    is an exclusion signal, which the lexer understands as ending the
    logical line.

    Thus, a comment has meaning at 'compile time', but not at 'execution
    time'. Such would be true, strictly-speaking. However, most of us would
    say that a comment 'has no meaning' in terms of the parser, and what it delivers.

    Shall we change the phrase to "everything in Python, at run-time, is an object"? As a phrase it is obiter-dictum, not ratio decidendi! (to use a language which has only extended in dubious modes for the last couple-of-thousand years - but which still has illogical structure)

    Suspect that clumsy exclusion also lacks precision to the standard being demanded. Thus return to the suggestion that you seem in the wrong
    place, because Python doesn't meet the required standard. Sorry!


    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico via Python-list on Mon Jan 15 14:10:29 2024
    On 15/01/24 11:47, Chris Angelico via Python-list wrote:
    On Mon, 15 Jan 2024 at 09:40, dn via Python-list <python-list@python.org> 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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico via Python-list on Mon Jan 15 14:41:25 2024
    On 15/01/24 14:33, Chris Angelico via Python-list wrote:
    On Mon, 15 Jan 2024 at 12:12, dn via Python-list <python-list@python.org> 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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Chris Angelico on Mon Jan 15 14:49:03 2024
    On 15/01/24 14:45, Chris Angelico wrote:
    On Mon, 15 Jan 2024 at 12:42, dn via Python-list <python-list@python.org> 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 <python-list@python.org> 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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Left Right on Mon Jan 15 20:53:03 2024
    On 15/01/24 1:28 am, Left Right wrote:
    Python isn't a context-free language, so the grammar that is used to
    describe it doesn't actually describe the language

    Very few languages have a formal grammar that *fully* describes
    the set of strings that constitute valid programs, including all
    the rules about things having to be declared, types matching up,
    etc. The only one I know of which attempted that is Algol 68,
    and it seems to be regarded as a technical success but a practical
    failure.

    ... so, it's a "pretend grammar" that ignores indentation.

    Indentation isn't ignored, it appears in the grammar by means of
    INDENT and DEDENT lexical tokens.

    It's true that the meaning of these tokens is described informally
    elsewhere, but that's true of all the lexical features.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Left Right on Mon Jan 15 20:37:35 2024
    On 13/01/24 11:34 pm, Left Right wrote:
    To make this
    shorter, Python allows:

    for <statement> in ... : ...


    Um, no, it doesn't. An assignment target is not, on its own, a
    statement.

    It's hard to make sense of what you're saying. You seem to be
    surprised by the fact that Python doesn't require variables to
    be declared separately from their use. But this is a very common
    feature of dynamic languages generally. As language oddities go,
    it hardly rates a mention.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to All on Mon Jan 15 21:13:41 2024
    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.

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Ewing@21:1/5 to Chris Angelico on Mon Jan 15 21:21:44 2024
    On 15/01/24 9:07 pm, Chris Angelico wrote:
    The grammar *can't* specify everything. If it did, it would have to
    have rules for combining individual letters into a NAME and individual characters into a string literal.

    The lexical level of a grammar can be, and often is, described
    formally using regular expressions.

    Although some might consider that this doesn't contradict
    your statement about readability. :-)

    --
    Greg

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Greg Ewing via Python-list on Mon Jan 15 22:37:15 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Antoon Pardon@21:1/5 to All on Mon Jan 15 10:52:02 2024
    Op 14/01/2024 om 13:28 schreef Left Right via Python-list:
    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.

    No it doesn't. Here is the definition of a block, it clearly mentions indentation:

    block:
    | NEWLINE INDENTstatements DEDENT
    | simple_stmts But you are correct that python in not a context-free language. But so is any programming language. Yet a lot of those non context-free language designers thought it helpful to have a
    modified/extended BNF description of a superset of the intended language
    and used other means to further check whether the code in question was
    valid or not. -- Antoon Pardon

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Antoon Pardon on Mon Jan 15 12:35:22 2024
    Antoon Pardon <antoon.pardon@vub.be> writes:
    No it doesn't. Here is the definition of a block, it clearly mentions >indentation:

    In many programming languages, whitespace is missing from the grammar.

    This is not an error in the grammar of those languages though, because
    the grammar actually is split into a "lexical" and a "syntactical"
    part. Whitespace is used in the lexical part to split the input into
    tokens. Then the grammar does not need to take whitespace into
    account anymore. It operates on the tokens from the lexical phase.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Rich Shepard on Mon Jan 29 16:41:14 2024
    Rich Shepard <rshepard@appl-ecosys.com> writes: how to specify a >variable in one file that has its values in another file.

    In the first file, you can write

    variable = eval( open( "otherfile" ).read() )

    , and the value for "variable" will be taken from "otherfile".

    $ echo 3.14 >otherfile
    $ echo "v = eval( open( 'otherfile' ).read() ); print( v )" > thisfile
    $ python3 thisfile
    3.14
    $

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Rich Shepard via Python-list on Mon Jan 29 08:15:44 2024
    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. :-)

    TIA,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dieter.maurer@online.de@21:1/5 to Rich Shepard on Mon Jan 29 18:20:43 2024
    Rich Shepard wrote at 2024-1-29 08:15 -0800:
    ...
    If this explanation is not sufficiently clear I'll re-write it. :-)

    Have you read "https://docs.python.org/3/library/io.html#module-io"?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Ribbens@21:1/5 to Rich Shepard on Mon Jan 29 17:51:13 2024
    On 2024-01-29, Rich Shepard <rshepard@appl-ecosys.com> wrote:
    On Mon, 29 Jan 2024, Rich Shepard via Python-list wrote:
    No, I hadn't ... but I am reading it now.

    Perhaps I missed the answer to my question when reading the io module. It explains how to open/write/read files of text and binary data, not passing
    a variable's value from one file to a place-keeper in another file.

    Why would it contain a recipe for performing some specific task that
    appears unique to you?

    If you want any meaningful help you'll need to explain more precisely
    what it is that you're trying to achieve and why.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to dieter.maurer@online.de on Mon Jan 29 09:27:08 2024
    On Mon, 29 Jan 2024, dieter.maurer@online.de wrote:

    Have you read "https://docs.python.org/3/library/io.html#module-io"?

    Dieter,

    No, I hadn't ... but I am reading it now.

    Many thanks,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Rich Shepard via Python-list on Mon Jan 29 09:37:55 2024
    On Mon, 29 Jan 2024, Rich Shepard via Python-list wrote:

    No, I hadn't ... but I am reading it now.

    Perhaps I missed the answer to my question when reading the io module. It explains how to open/write/read files of text and binary data, not passing
    a variable's value from one file to a place-keeper in another file.

    I'll keep searching for a solution.

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to avi.e.gross@gmail.com on Mon Jan 29 10:05:25 2024
    On Mon, 29 Jan 2024, avi.e.gross@gmail.com wrote:

    There are several general solutions that may apply. Some involve reading
    in both files into data structures and perhaps linking them together in
    some way such as a data.frame or binary tree. You can then process
    individual request in memory/

    Avi,

    I found several web pages describing how to use the python email library and tools to send individual or multiple email messages. I'll learn how to do
    this based on a couple of detailed examples.

    Thanks,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Rich Shepard via Python-list on Tue Jan 30 08:10:48 2024
    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 "alice@domain.tld", how could one know if "Bob"
    actually corresponds to "list-member@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Rich Shepard via Python-list on Mon Jan 29 19:47:15 2024
    On 1/29/2024 11:15 AM, 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. :-)

    TIA,

    Rich

    I'm assuming this is a continuation of a previous thread about working
    with alternate lines with salutation and address, and I assume you've
    got that worked out.

    If you aren't going to use one or another existing template system,
    perhaps the easiest is to use unique strings in the message file. For
    example:

    Dear __##so-and-so##__:
    Please don't write this message off as mere spam.
    Respectfully, Rich

    Then you just do a replace of the unique string by the salutation. Don't
    change the original (i.e., template), make the changes to a copy that
    you will output.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jon Ribbens@21:1/5 to Rich Shepard on Tue Jan 30 14:03:39 2024
    On 2024-01-30, Rich Shepard <rshepard@appl-ecosys.com> wrote:
    On Mon, 29 Jan 2024, Thomas Passin via Python-list wrote:

    If you aren't going to use one or another existing template system,
    perhaps the easiest is to use unique strings in the message file. For
    example:

    Dear __##so-and-so##__:
    Please don't write this message off as mere spam.
    Respectfully, Rich

    Then you just do a replace of the unique string by the salutation. Don't
    change the original (i.e., template), make the changes to a copy that you
    will output.

    My script is not a web application, but an emailer that allows me to contact clients and prospective clients. From the command line on a linux host.
    Using the python smtplib and mail modules.

    lol good luck with that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Thomas Passin via Python-list on Tue Jan 30 05:37:35 2024
    On Mon, 29 Jan 2024, Thomas Passin via Python-list wrote:

    If you aren't going to use one or another existing template system,
    perhaps the easiest is to use unique strings in the message file. For example:

    Dear __##so-and-so##__:
    Please don't write this message off as mere spam.
    Respectfully, Rich

    Then you just do a replace of the unique string by the salutation. Don't change the original (i.e., template), make the changes to a copy that you will output.

    My script is not a web application, but an emailer that allows me to contact clients and prospective clients. From the command line on a linux host.
    Using the python smtplib and mail modules.

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Rich Shepard via Python-list on Tue Jan 30 09:07:52 2024
    On 1/30/2024 8:37 AM, Rich Shepard via Python-list wrote:
    On Mon, 29 Jan 2024, Thomas Passin via Python-list wrote:

    If you aren't going to use one or another existing template system,
    perhaps the easiest is to use unique strings in the message file. For
    example:

    Dear __##so-and-so##__:
      Please don't write this message off as mere spam.
      Respectfully, Rich

    Then you just do a replace of the unique string by the salutation. Don't
    change the original (i.e., template), make the changes to a copy that you
    will output.

    My script is not a web application, but an emailer that allows me to
    contact
    clients and prospective clients. From the command line on a linux host.
    Using the python smtplib and mail modules.

    Rich

    Fine, my toy example will still be applicable. But, you know, you
    haven't told us enough to give you help. Do you want to replace text
    from values in a file? That's been covered. Do you want to send the
    messages using those libraries? You haven't said what you don't know
    how to do. Something else? What is it that you want to do that you
    don't know how?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Thomas Passin via Python-list on Tue Jan 30 09:21:51 2024
    On Tue, 30 Jan 2024, Thomas Passin via Python-list wrote:

    Fine, my toy example will still be applicable. But, you know, you haven't told us enough to give you help. Do you want to replace text from values
    in a file? That's been covered. Do you want to send the messages using
    those libraries? You haven't said what you don't know how to do. Something else? What is it that you want to do that you don't know how?

    Thomas,

    For 30 years I've used a bash script using mailx to send messages to a list
    of recipients. They have no salutation to personalize each one. Since I want
    to add that personalized salutation I decided to write a python script to replace the bash script.

    I have collected 11 docs explaining the smtplib and email modules and
    providing example scripts to apply them to send multiple individual messages with salutations and attachments.

    Today I'm going to be reading these. They each recommend using .csv input
    files for names and addresses. My first search is learning whether I can
    write a single .csv file such as:
    "name1","address1"
    "mane2","address2"
    which I believe will work; and by inserting at the top of the message block
    Hi, {yourname}
    the name in the .csv file will replace the bracketed place holder.

    Still much to learn and the batch of downloaded PDF files should educate me.

    Regards,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to AVI GROSS via Python-list on Tue Jan 30 09:25:48 2024
    On Tue, 30 Jan 2024, AVI GROSS via Python-list wrote:

    But seriously, the OP, AKA Rich, is making clear that he is making a tool
    for his own use. It sounds like he wants to maintain a data repository of
    his own with some info about his clients and then have the ability to
    specify a name and pop up an email directed to them, or something along
    those lines.

    Close, Avi.

    I have no issues sending messages to single individuals or mailing lists. I want to send the same message to several individuals at one time, which I've done -- without individual salutations -- for 30 years using a bash script
    and mailx.

    As I replied to Thomas on the list, I've downloaded 11 PDF docs from the Web (and a useful book on the Python3 standard library) and will start reading
    and learning from them today. I expect to find answers to my few remaining questions in these docs.

    Regards,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Rich Shepard via Python-list on Tue Jan 30 22:36:49 2024
    On 1/30/2024 12:21 PM, Rich Shepard via Python-list wrote:
    On Tue, 30 Jan 2024, Thomas Passin via Python-list wrote:

    Fine, my toy example will still be applicable. But, you know, you haven't
    told us enough to give you help. Do you want to replace text from values
    in a file? That's been covered. Do you want to send the messages using
    those libraries? You haven't said what you don't know how to do.
    Something
    else? What is it that you want to do that you don't know how?

    Thomas,

    For 30 years I've used a bash script using mailx to send messages to a list of recipients. They have no salutation to personalize each one. Since I
    want
    to add that personalized salutation I decided to write a python script to replace the bash script.

    I have collected 11 docs explaining the smtplib and email modules and providing example scripts to apply them to send multiple individual
    messages
    with salutations and attachments.

    If I had a script that's been working for 30 years, I'd probably just
    use Python to do the personalizing and let the rest of the bash script
    do the rest, like it always has. The Python program would pipe or send
    the personalized messages to the rest of the bash program. Something in
    that ballpark, anyway.

    Today I'm going to be reading these. They each recommend using .csv input files for names and addresses. My first search is learning whether I can write a single .csv file such as:
    "name1","address1"
    "mane2","address2"
    which I believe will work; and by inserting at the top of the message block Hi, {yourname}
    the name in the .csv file will replace the bracketed place holder
    If the file contents are going to be people's names and email addresses,
    I would just tab separate them and split each line on the tab. Names
    aren't going to include tabs so that would be safe. Email addresses
    might theoretically include a tab inside a quoted name but that would be extremely obscure and unlikely. No need for CSV, it would just add
    complexity.

    data = f.readlines()
    for d in data:
    name, addr = line.split('\t') if line.strip() else ('', '')

    Still much to learn and the batch of downloaded PDF files should educate
    me.

    Regards,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to avi.e.gross@gmail.com on Wed Jan 31 07:25:12 2024
    On 1/30/2024 11:25 PM, avi.e.gross@gmail.com wrote:
    Thomas, on some points we may see it differently.

    I'm mostly going by what the OP originally asked for back on Jan 11.
    He's been too stingy with information since then to be worth spending
    much time on, IMHO.

    Some formats can be done simply but are maybe better done in somewhat standard ways.

    Some of what the OP has is already tables in a database and that can trivially be exported into a CSV file or other formats like your TSV file
    and more. They can also import from there. As I mentioned, many spreadsheets and all kinds of statistical programs tend to support some formats making it quite flexible.

    Python has all kinds of functionality, such as in the pandas module, to read in a CSV or write it out. And once you have the data structure in memory, al kinds of queries and changes can be made fairly straightforwardly. As one example, Rich has mentioned wanting finer control in selecting who gets some version of the email based on concepts like market segmentation. He already may have info like the STATE (as in Arizona) in his database. He might at some point enlarge his schema so each entry is placed in one or more categories and thus his CSV, once imported, can do the usual tasks of selecting various rows and columns or doing joins or whatever.

    Mind you, another architecture could place quite a bit of work completely on the back end and he could send SQL queries to the database from python and get back his results into python which would then make the email messages
    and pass them on to other functionality to deliver. This would remove any need for files and just rely on the DB.

    There as as usual, too many choices and not necessarily one best answer. Of course if this was a major product that would be heavily used, sure, you could tweak and optimize. As it is, Rich is getting a chance to improve his python skills no matter which way he goes.



    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Thomas Passin via Python-list
    Sent: Tuesday, January 30, 2024 10:37 PM
    To: python-list@python.org
    Subject: Re: Extract lines from file, add to new files

    On 1/30/2024 12:21 PM, Rich Shepard via Python-list wrote:
    On Tue, 30 Jan 2024, Thomas Passin via Python-list wrote:

    Fine, my toy example will still be applicable. But, you know, you haven't >>> told us enough to give you help. Do you want to replace text from values >>> in a file? That's been covered. Do you want to send the messages using
    those libraries? You haven't said what you don't know how to do.
    Something
    else? What is it that you want to do that you don't know how?

    Thomas,

    For 30 years I've used a bash script using mailx to send messages to a
    list
    of recipients. They have no salutation to personalize each one. Since I
    want
    to add that personalized salutation I decided to write a python script to
    replace the bash script.

    I have collected 11 docs explaining the smtplib and email modules and
    providing example scripts to apply them to send multiple individual
    messages
    with salutations and attachments.

    If I had a script that's been working for 30 years, I'd probably just
    use Python to do the personalizing and let the rest of the bash script
    do the rest, like it always has. The Python program would pipe or send
    the personalized messages to the rest of the bash program. Something in
    that ballpark, anyway.

    Today I'm going to be reading these. They each recommend using .csv input
    files for names and addresses. My first search is learning whether I can
    write a single .csv file such as:
    "name1","address1"
    "mane2","address2"
    which I believe will work; and by inserting at the top of the message
    block
    Hi, {yourname}
    the name in the .csv file will replace the bracketed place holder
    If the file contents are going to be people's names and email addresses,
    I would just tab separate them and split each line on the tab. Names
    aren't going to include tabs so that would be safe. Email addresses
    might theoretically include a tab inside a quoted name but that would be extremely obscure and unlikely. No need for CSV, it would just add complexity.

    data = f.readlines()
    for d in data:
    name, addr = line.split('\t') if line.strip() else ('', '')

    Still much to learn and the batch of downloaded PDF files should educate
    me.

    Regards,

    Rich


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich Shepard@21:1/5 to Thomas Passin via Python-list on Wed Jan 31 06:05:33 2024
    On Tue, 30 Jan 2024, Thomas Passin via Python-list wrote:

    If I had a script that's been working for 30 years, I'd probably just use Python to do the personalizing and let the rest of the bash script do the rest, like it always has. The Python program would pipe or send the personalized messages to the rest of the bash program. Something in that ballpark, anyway.

    Thomas,

    A bash shell script looks easier for me and more promising. Using a while
    loop (one for the name file the other for the address file), and sed for putting the name at the head of the message replacing a generic placeholder should work with the existing for loop script.

    Thanks,

    Rich

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to Rich Shepard via Python-list on Wed Jan 31 10:36:24 2024
    On 1/31/2024 9:05 AM, Rich Shepard via Python-list wrote:
    On Tue, 30 Jan 2024, Thomas Passin via Python-list wrote:

    If I had a script that's been working for 30 years, I'd probably just use
    Python to do the personalizing and let the rest of the bash script do the
    rest, like it always has. The Python program would pipe or send the
    personalized messages to the rest of the bash program. Something in that
    ballpark, anyway.

    Thomas,

    A bash shell script looks easier for me and more promising. Using a while loop (one for the name file the other for the address file), and sed for putting the name at the head of the message replacing a generic placeholder should work with the existing for loop script.

    Sounds good. I'd still be a bit worried about the two files getting out
    of sync, as others have mentioned.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to avi.e.gross@gmail.com on Sat Feb 3 12:58:57 2024
    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.

    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.

    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.

    On 2/3/2024 11:33 AM, avi.e.gross@gmail.com wrote:
    Thomas,

    I have been thinking about the concept of being stingy with information as this is a fairly common occurrence when people ask for help. They often ask for what they think they want while people like us keep asking why they want that and perhaps offer guidance on how to get closer to what they NEED or a better way.

    In retrospect, Rich did give all the info he thought he needed. It boiled down to saying that he wants to distribute data into two files in such a way that finding an item in file A then lets him find the corresponding item in file B. He was not worried about how to make the files or what to do with
    the info afterward. He had those covered and was missing what he considered
    a central piece. And, it seems he programs in multiple languages and environments as needed and is not exactly a newbie. He just wanted a way to implement his overall design.

    We threw many solutions and ideas at him but some of us (like me) also got frustrated as some ideas were not received due to one objection or another that had not been mentioned earlier when it was not seen as important.

    I particularly notice a disconnect some of us had. Was this supposed to be a search that read only as much as needed to find something and stopped reading, or a sort of filter that returned zero or more matches and went to the end, or perhaps something that read entire files and swallowed them into data structures in memory and then searched and found corresponding entries, or maybe something else?

    All the above approaches could work but some designs not so much. For example, some files are too large. We, as programmers, often consciously or unconsciously look at many factors to try to zoom in on what approaches me might use. To be given minimal amounts of info can be frustrating. We worry about making a silly design. But the OP may want something minimal and not worry as long as it is fairly easy to program and works.

    We could have suggested something very simple like:

    Open both files A and B
    In a loop get a line from each. If the line from A is a match, do something with the current line from B.
    If you are getting only one, exit the loop.

    Or, if willing, we could have suggested any other file format, such as a
    CSV, in which the algorithm is similar but different as in:

    Open file A
    Read a line in a loop
    Split it in parts
    If the party of the first part matches something, use the party of the
    second part

    Or, of course, suggest they read the entire file, into a list of lines or a data.frame and use some tools that search all of it and produce results.

    I find I personally now often lean toward the latter approach but ages ago when memory and CPU were considerations and maybe garbage collection was not automatic, ...


    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org> On Behalf Of Thomas Passin via Python-list
    Sent: Wednesday, January 31, 2024 7:25 AM
    To: python-list@python.org
    Subject: Re: Extract lines from file, add to new files

    On 1/30/2024 11:25 PM, avi.e.gross@gmail.com wrote:
    Thomas, on some points we may see it differently.

    I'm mostly going by what the OP originally asked for back on Jan 11.
    He's been too stingy with information since then to be worth spending
    much time on, IMHO.

    Some formats can be done simply but are maybe better done in somewhat
    standard ways.

    Some of what the OP has is already tables in a database and that can
    trivially be exported into a CSV file or other formats like your TSV file
    and more. They can also import from there. As I mentioned, many
    spreadsheets
    and all kinds of statistical programs tend to support some formats making
    it
    quite flexible.

    Python has all kinds of functionality, such as in the pandas module, to
    read
    in a CSV or write it out. And once you have the data structure in memory,
    al
    kinds of queries and changes can be made fairly straightforwardly. As one
    example, Rich has mentioned wanting finer control in selecting who gets
    some
    version of the email based on concepts like market segmentation. He
    already
    may have info like the STATE (as in Arizona) in his database. He might at
    some point enlarge his schema so each entry is placed in one or more
    categories and thus his CSV, once imported, can do the usual tasks of
    selecting various rows and columns or doing joins or whatever.

    Mind you, another architecture could place quite a bit of work completely
    on
    the back end and he could send SQL queries to the database from python and >> get back his results into python which would then make the email messages
    and pass them on to other functionality to deliver. This would remove any
    need for files and just rely on the DB.

    There as as usual, too many choices and not necessarily one best answer.
    Of
    course if this was a major product that would be heavily used, sure, you
    could tweak and optimize. As it is, Rich is getting a chance to improve
    his
    python skills no matter which way he goes.



    -----Original Message-----
    From: Python-list <python-list-bounces+avi.e.gross=gmail.com@python.org>
    On
    Behalf Of Thomas Passin via Python-list
    Sent: Tuesday, January 30, 2024 10:37 PM
    To: python-list@python.org
    Subject: Re: Extract lines from file, add to new files

    On 1/30/2024 12:21 PM, Rich Shepard via Python-list wrote:
    On Tue, 30 Jan 2024, Thomas Passin via Python-list wrote:

    Fine, my toy example will still be applicable. But, you know, you
    haven't
    told us enough to give you help. Do you want to replace text from values >>>> in a file? That's been covered. Do you want to send the messages using >>>> those libraries? You haven't said what you don't know how to do.
    Something
    else? What is it that you want to do that you don't know how?

    Thomas,

    For 30 years I've used a bash script using mailx to send messages to a
    list
    of recipients. They have no salutation to personalize each one. Since I
    want
    to add that personalized salutation I decided to write a python script to >>> replace the bash script.

    I have collected 11 docs explaining the smtplib and email modules and
    providing example scripts to apply them to send multiple individual
    messages
    with salutations and attachments.

    If I had a script that's been working for 30 years, I'd probably just
    use Python to do the personalizing and let the rest of the bash script
    do the rest, like it always has. The Python program would pipe or send
    the personalized messages to the rest of the bash program. Something in
    that ballpark, anyway.

    Today I'm going to be reading these. They each recommend using .csv input >>> files for names and addresses. My first search is learning whether I can >>> write a single .csv file such as:
    "name1","address1"
    "mane2","address2"
    which I believe will work; and by inserting at the top of the message
    block
    Hi, {yourname}
    the name in the .csv file will replace the bracketed place holder
    If the file contents are going to be people's names and email addresses,
    I would just tab separate them and split each line on the tab. Names
    aren't going to include tabs so that would be safe. Email addresses
    might theoretically include a tab inside a quoted name but that would be
    extremely obscure and unlikely. No need for CSV, it would just add
    complexity.

    data = f.readlines()
    for d in data:
    name, addr = line.split('\t') if line.strip() else ('', '')

    Still much to learn and the batch of downloaded PDF files should educate >>> me.

    Regards,

    Rich



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mats Wichmann@21:1/5 to Thomas Passin via Python-list on Sat Feb 3 11:56:37 2024
    On 2/3/24 10: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.

    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.

    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.

    Indeed. I've occasionally practised the following technique (in some
    form) over the years without knowing it had grown a name, and wikipedia
    page to go with it. It may be handy to use to help come up with a
    clearer explanation before sending off a post to a mailing list or other static medium, because of the inevitable delays in going back and forth. Interactive formus like the Python Discord have a bit of an advantage in
    that you can try to tease out the intent more quickly. But as you
    say... a newcomer won't know this.

    https://en.wikipedia.org/wiki/Rubber_duck_debugging

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Thomas Passin via Python-list on Sun Feb 4 11:02:17 2024
    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' Python knowledge, or whatever; isn't such one of the rationales for this DiscussionList?

    That said, we're all volunteering our (valuable) time!
    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Passin@21:1/5 to dn via Python-list on Sat Feb 3 17:41:41 2024
    On 2/3/2024 5:02 PM, dn via Python-list wrote:
    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)

    Pairs programming can be fun and productive, if you are lucky to have
    the right person to work with. I've had one person like that over the
    years.

    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' Python knowledge, or whatever; isn't such one of the rationales for this DiscussionList?

    That said, we're all volunteering our (valuable) time!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to avi.e.gross@gmail.com on Mon Feb 5 11:01:00 2024
    On 4/02/24 13:20, avi.e.gross@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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)