Re: Best use of "open" context manager
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
> 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
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
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
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
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
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
> 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
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