Re: Best use of "open" context manager

2024-07-06 Thread Richard Damon via Python-list

My thoughts is that if the "many lines of code" puts the except to far
from the try, then perhaps it would have made sense to factor out some
part there into a function.

Perhaps like:

try:
   with open(FileName) as f:
  for ln in f{
 process(ln)
except FileNotFoundError:
   print(f"File {FileName} not found:")
   sys.exit()

Now the "process" function has been factored out and can be well
documented as to what it is doing on each line, and this code can be
documented as running process on each line of the file.

On 7/6/24 6:49 AM, Rob Cliffe via Python-list wrote:

Consider this scenario (which I ran into in real life):
    I want to open a text file and do a lot of processing on the lines
of that file.
    If the file does not exist I want to take appropriate action, e.g.
print an error message and abort the program.
I might write it like this:

try:
    with open(FileName) as f:
        for ln in f:
            print("I do a lot of processing here")
            # Many lines of code here .
except FileNotFoundError:
    print(f"File {FileName} not found")
    sys.exit()

but this violates the principle that a "try" suite should be kept
small, so that only targeted exceptions are trapped,
not to mention that having "try" and "except" far apart decreases
readability.

Or I might write it like this:

try:
    f = open(FileName) as f:
    FileLines = f.readlines()
except FileNotFoundError:
    print(f"File {FileName} not found")
    sys.exit()
# I forgot to put "f.close()" here -:)
for ln in File Lines:
        print("I do a lot of processing here")
        # Many lines of code here .

but this loses the benefits of using "open" as a context manager,
and would also be unacceptable if the file was too large to read into
memory.

Really I would like to write something like

try:
    with open(FileName) as f:
except FileNotFoundError:
    print(f"File {FileName} not found")
    sys.exit()
else: # or "finally:"
        for ln in f:
            print("I do a lot of processing here")
            # Many lines of code here .

but this of course does not work because by the time we get to "for ln
in f:" the file has been closed so we get
ValueError: I/O operation on closed file

I could modify the last attempt to open the file twice, which would
work, but seems like a kludge (subject to race condition, inefficient).

Is there a better / more Pythonic solution?

Best wishes
Rob Cliffe



--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list


Re: UTF_16 question

2024-04-29 Thread Richard Damon via Python-list
> On Apr 29, 2024, at 12:23 PM, jak via Python-list  
> wrote:
> 
> Hi everyone,
> one thing that I do not understand is happening to me: I have some text
> files with different characteristics, among these there are that they
> have an UTF_32_le coding, utf_32be, utf_16_le, utf_16_be all of them
> without BOM. With those utf_32_xx I have no problem but with the
> UTF_16_xx I have. If I have an utf_16_le coded file and I read it with
> encoding='utf_16_le' I have no problem I read it, with
> encoding='utf_16_be' I can read it without any error even if the data I
> receive have the inverted bytes. The same thing happens with the
> utf_16_be codified file, I read it, both with encoding='utf_16_be' and
> with 'utf_16_le' without errors but in the last case the bytes are
> inverted. What did I not understand? What am I doing wrong?
> 
> thanks in advance
> 
> --
> https://mail.python.org/mailman/listinfo/python-list

That is why the BOM was created. A lot of files can be “correctly” read as 
either UTF-16-LE or UTF-1-BE encoded, as most of the 16 bit codes are valid, so 
unless the wrong encoding happens to hit something that is invalid (most likely 
something looking like a Surrogage Pair without a match), there isn’t an error 
in reading the file. The BOM character was specifically designed to be an 
invalid code if read by the wrong encoding (if you ignore the possibility of 
the file having a NUL right after the BOM)

If you know the files likely contains a lot of “ASCII” characters, then you 
might be able to detect that you got it wrong, due to seeing a lot of 0xXX00 
characters and few 0x00XX characters, but that doesn’t create an “error” 
normally.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Python misbehavior

2024-02-08 Thread Richard Damon via Python-list

On 2/6/24 10:46 PM, Jim via Python-list wrote:

Friends,
Please forgive me if this is not the proper forum for dealing with an issue of mine, but 
I am at a loss in finding a fix for a python problem in the program ClipGrab. The program 
allows one to download videos or audios from YouTube and other media sites. My limited 
understanding of the process suggests that python facilitates the transfer of data from 
YouTube to ClipGrab. As of recently, I am unable to use the ClipGrab program and the 
issue at fault has something to do with python. In an "about" screen within 
ClipGrab my (now) incapable python script reads:

youtube-dlp: (C:\Program Files (x86)\ClipGrab\python\python.exe: can't find '_main_' 
module in " ) Python: C:/Program Files (x86)/ClipGrab/python/python.exe (Python 
3.8.9)

Since this problem began I downloaded ClipGrab on to another desktop computer and it runs perfectly 
without a problem. The script on the "about" page does not indicate anything about 
"can't find -main- module" etc. Is there any advice you can offer to overcome this and 
recover my downloading connections to YouTube? Or, if this is the wrong group to handle such 
issues, could you please pass my message on to a better choice?

Gratefully,
Jim Haas

Sent from my iPhone


Python itself doesn't have any code to do this, but does have some
support libraries that help.

It looks like your "ClipGrab" program is using the python module
"youtube-dlp" to get the data (that module probabaly has the details of
how to do the operation), but somehow ClipGrab hasn't packaged the
module into itself properly.

You probably should seek help with the support for the ClipGrab program
from the people that make it.

If you look up the documentation for youtube-dlp, you may find that you
can use that module directly, and not need the ClipGrab wrapper at all
(though it may provide some benefits if you can get it working again).


--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list


Re: How/where to store calibration values - written by program A, read by program B

2023-12-28 Thread Richard Damon via Python-list



 On 12/28/2023 12:20 AM EST rbowman via Python-list
 <[1]python-list@python.org> wrote:


 On Wed, 27 Dec 2023 03:53:42 -0600, Greg Walters wrote:


   The biggest caveat is that the shared variable MUST exist before it
   can
   be examined or used (not surprising).

 There are a few other questions. Let's say config.py contains a variable
 like 'font' that is a user set preference or a calibration value
 calculated by A to keep with the thread title. Assuming both scripts are
 running, how does the change get propagated to B after it is set in A
 and
 written to the shared file? Is there a mechanism to allow both scripts
 to
 make updates?

 The easy way out is to assume the changes will be picked up when the
 scripts are restarted but this is not always acceptable.

 --
 [2]https://mail.python.org/mailman/listinfo/python-list

   If one module does a:

   import config

   config.font = "New Value"

   Then every other module in that program that also did a

   import config

   will see the new value of that variable, as the assignment rebound the
   name in the module namespace to the new value.

   Note, it does NOT work if you did a

   from config import font

   font = "New Value"



   as that doesn't change the binding in the config module.

   IF you need to propagate to a different process, you need something
   different.


References

   Visible links
   1. mailto:python-list@python.org
   2. https://mail.python.org/mailman/listinfo/python-list
-- 
https://mail.python.org/mailman/listinfo/python-list


Context without manager

2023-11-27 Thread Richard Damon via Python-list
Read the Fine context manager documentation.
What “with with_expression as var” does is effectively:

ob = with_expression
var = ob.__enter__()

And then at the end of the with, does a
ob.__exit__()

(With some parameters to __exit__, that could just be None, None, None for the 
simplest case).

Note, YOUR program must now make sure that the __exit__ function is called, and 
handle any exceptions that got thrown, and that ob and var are put somewhere 
you can access them at that later time.


> On Nov 27, 2023, at 12:24 PM, Piergiorgio Sartor via Python-list 
>  wrote:
> 
> On 26/11/2023 18.50, Dieter Maurer wrote:
>> Piergiorgio Sartor wrote at 2023-11-25 22:15 +0100:
>>> ...
>>> Apparently, the "with" context manager is not usable
>>> in classes, at least not with __init__() & co.
>> You can use `with` in classes -- with any context manager.
>> However, you would usually not use `with` with a file you have opened
>> in `__init__`.
>> If a class defines `__enter__` and `__exit__` (i.e.
>> the "cntext manager protocol"), then its instances
>> can be used with the `with` statement.
>> The important use case for a context manager is the
>> situation:
>>  set up a context (--> method `__enter__`)
>>  perform some operations in this context (--> body of `with` statement)
>>  tear down the context (--> method `__exit__`).
>> If you do not have this case (e.g. usually if you open the file
>> in a class's `__init__`), you do not use a context manager.
> 
> Very clear, but what if the class is *not* "open()",
> but something else _requiring_ using "with"?
> How to do this in a "__init__()" of a class?
> 
> In other words, what if "open()" could *only* be used
> with "with" and not just by assigning "fp = open()"?
> 
> The problem is I've some SDK of some device which
> provides context manager *only* classes.
> 
> I *cannot* do:
> 
> device = device_open(...)
> device.do_something()
> device.close()
> 
> I *must* do:
> 
> with device_open() as device:
> device.do_something()
> 
> Nevertheless, I _need_ to have a class
> where the device is opened in the __init__()
> and used in some methods.
> 
> Any ideas?
> 
> bye,
> 
> --
> 
> piergiorgio
> 
> --
> https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Context without manager

2023-11-27 Thread Richard Damon via Python-list
Read the Fine context manager documentation.
What “with with_expression as var” does is effectively:

ob = with_expression
var = ob.__enter__()

And then at the end of the with, does a
ob.__exit__()

(With some parameters to __exit__, that could just be None, None, None for the 
simplest case).

Note, YOUR program must now make sure that the __exit__ function is called, and 
handle any exceptions that got thrown, and that ob and var are put somewhere 
you can access them at that later time.


> On Nov 27, 2023, at 12:24 PM, Piergiorgio Sartor via Python-list 
>  wrote:
> 
> On 26/11/2023 18.50, Dieter Maurer wrote:
>> Piergiorgio Sartor wrote at 2023-11-25 22:15 +0100:
>>> ...
>>> Apparently, the "with" context manager is not usable
>>> in classes, at least not with __init__() & co.
>> You can use `with` in classes -- with any context manager.
>> However, you would usually not use `with` with a file you have opened
>> in `__init__`.
>> If a class defines `__enter__` and `__exit__` (i.e.
>> the "cntext manager protocol"), then its instances
>> can be used with the `with` statement.
>> The important use case for a context manager is the
>> situation:
>>   set up a context (--> method `__enter__`)
>>   perform some operations in this context (--> body of `with` statement)
>>   tear down the context (--> method `__exit__`).
>> If you do not have this case (e.g. usually if you open the file
>> in a class's `__init__`), you do not use a context manager.
> 
> Very clear, but what if the class is *not* "open()",
> but something else _requiring_ using "with"?
> How to do this in a "__init__()" of a class?
> 
> In other words, what if "open()" could *only* be used
> with "with" and not just by assigning "fp = open()"?
> 
> The problem is I've some SDK of some device which
> provides context manager *only* classes.
> 
> I *cannot* do:
> 
> device = device_open(...)
> device.do_something()
> device.close()
> 
> I *must* do:
> 
> with device_open() as device:
> device.do_something()
> 
> Nevertheless, I _need_ to have a class
> where the device is opened in the __init__()
> and used in some methods.
> 
> Any ideas?
> 
> bye,
> 
> --
> 
> piergiorgio
> 
> --
> https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: type annotation vs working code

2023-10-01 Thread Richard Damon via Python-list
My view of the issue is that the "trick" of "evaluating" a name to see 
if the object has been initialized is just a tad on the "tricky" side, 
and the annotation/value is really incorrect.


The name at the point you are annotating it, isn't really a "bool" 
because a bool will always have either the value "True" or "False", 
while for this variable, you are really testing if it exists or not.


Perhaps a better method would be rather than just using the name and 
catching the exception, use a real already_initialized flag (set to True 
when you initialize), and look it up with getattr() with a default value 
of False.


--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list


Re: GNU gettext: Print string translated and untranslated at the same time

2023-08-17 Thread Richard Damon via Python-list
> On Aug 17, 2023, at 10:02 AM, c.buhtz--- via Python-list 
>  wrote:
> 
> X-Post: https://stackoverflow.com/q/76913082/4865723
> 
> I want to display one string in its original source (untranslated) version 
> and in its translated version site by site without duplicating the string in 
> the python source code?
> It wouldn't be a big deal if it is only one word.
> 
>print('The translated string "{}" is originally "{}".'.format(_('Hello'), 
> 'Hello'))
> 
> But in my situation it is a multi line string containing multiple paragraphs. 
> It is a full text. I don't want to duplicate that string.
> 
># Imagine 'Hello' as a 50x70 characters multi line string.
>original = 'Hello'
>translated = _('Hello')
>print('The translated string "{}" is originally "{}".'.format(translated, 
> original))
> 
> I do use the "class based API" of GNU gettext. My current approach, which is 
> not working, is to somehow (how!?) disable (or mask) the translation function 
> "_()" temporarily.
> But as described in the stackoverflow question (see first line of this mail) 
> this do not work.
> 
> def foobar(translate):
>if not translate:
># I try to mask the global _() builtins-function
>def _(txt):
>return txt
> 
>return _('Hello')
> 
> if __name__ == '__main__':
> 
># To ilustrate that _() is part of "builtins" namespace
>print(_('No problem.'))
> 
>print('The translated string "{}" is originally "{}".'
>  .format(foobar(True), foobar(False)))
> 
> This is the output:
> 
>Traceback (most recent call last):
>  File "/home/user/ownCloud/_transfer/./z.py", line 27, in 
>.format(foobar(True), foobar(False)))
>  File "/home/user/ownCloud/_transfer/./z.py", line 19, in foobar
>return _('Hello')
>UnboundLocalError: local variable '_' referenced before assignment
> 
> The full MWE can be found at stackoverflow 
> (https://stackoverflow.com/q/76913082/4865723).
> 
> The question is if this can be solved somehow or if there is an alternative 
> approach.
> The "_()" function is installed in the builtins namespace because of gettext 
> class based API. This is nice.
> Maybe I can somehow manipulate that builtins namespace? I tried to import 
> builtins and played around with it but couldn't find a way to do it.
> 
> Thanks
> Christian Buhtz
> 
> PS: This is IMHO not relevant for my question but if someone is interested 
> the connection to productive code can be found in this issue: 
> https://github.com/bit-team/backintime/issues/1473 There I describe what I 
> want to achive and also provide a GUI mockup.
> -- 
> https://mail.python.org/mailman/listinfo/python-list

One thing to remember is that the _() function, which calls gettext doesn’t 
need a literal string, so you can set a variable to ‘raw’ string, and then 
translate it to another variable, so you can have both.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Multiple inheritance and a broken super() chain

2023-07-03 Thread Richard Damon via Python-list

On 7/3/23 1:38 PM, Peter Slížik via Python-list wrote:

Hello.

The legacy code I'm working with uses a classic diamond inheritance. Let me
call the classes *Top*, *Left*, *Right*, and *Bottom*.
This is a trivial textbook example. The classes were written in the
pre-super() era, so all of them initialized their parents and Bottom
initialized both Left and Right in this order.

The result was expected: *Top* was initialized twice:

Top.__init__() Left.__init__() Top.__init__() Right.__init__()
Bottom.__init__()

Now I replaced all parent init calls with *super()*. After this, Top was
initialized only once.

Top.__init__() Right.__init__() Left.__init__() Bottom.__init__()

But at this point, I freaked out. The code is complex and I don't have the
time to examine its inner workings. And before, everything worked correctly
even though Top was initialized twice. So I decided to break the superclass
chain and use super() only in classes inheriting from a single parent. My
intent was to keep the original behavior but use super() where possible to
make the code more readable.

class Top:
def __init__(self):
print("Top.__init__()")

class Left(Top):
def __init__(self):
super().__init__()
print("Left.__init__()")

class Right(Top):
def __init__(self):
super().__init__()
print("Right.__init__()")

class Bottom(Left, Right):
def __init__(self):
Left.__init__(self) # Here I'm calling both parents manually
Right.__init__(self)
print("Bottom.__init__()")

b = Bottom()


The result has surprised me:

Top.__init__() Right.__init__() Left.__init__() Top.__init__()
Right.__init__() Bottom.__init__()

Now, as I see it, from the super()'s point of view, there are two
inheritance chains, one starting at Left and the other at Right. But
*Right.__init__()* is called twice. What's going on here?

Thanks,
Peter


Because the MRO from Bottom is [Bottom, Left, Right, Top] so super() in 
Left is Right. It doesn't go to Top as the MRO knows that Right should 
go to Top, so Left needs to go to Right to init everything, and then 
Bottom messes things up by calling Right again.


--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list