Re: Single line if statement with a continue
r...@zedat.fu-berlin.de (Stefan Ram) writes: >>"No multiple returns" is often found in programming guidelines. > > I religiously followed that when I did more C programming > than today. Then, I read an article about how the result > pattern makes functions measurably slower. (It should not > with an optimizing compiler, but it did due to those > measurements. Can't find that article now, though.) That makes me think about the quote from Edsger W. Dijkstra about the go to statement: Please do not fall into the trap of believing that I am terribly dogmatic about the go to statement. I have the uncomfortable feeling that others are making a religion out of it, as if the conceptual problems of programming could be solved by a simple trick, by a simple form of coding discipline! -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: How to get the needed version of a dependency
DFS writes: > On 12/14/2022 3:55 AM, Cecil Westerhof wrote: >> If I want to know the dependencies for requests I use: >> pip show requests >> And one of the lines I get is: >> Requires: certifi, charset-normalizer, idna, urllib3 >> But I want (in this case) to know with version of charset-normalizer >> requests needs. >> How do I get that? > > Check the METADATA file in the *dist-info package files usually found in > Lib\site-packages. > > ie \Python\3.11.0\Lib\site-packages\pandas-1.5.2.dist-info > > Look for config lines beginning with 'Requires': > > Requires-Python: >=3.8 > Requires-Dist: python-dateutil (>=2.8.1) > > $ pip list will show you which version of the package you have > installed, so you can search for the matching .dist-info file Works. In /usr/local/lib/python3.9/dist-packages/requests-2.28.1.dist-info/METADATA I see: Requires-Dist: charset-normalizer (<3,>=2) That already keeps charset-normalizer two months from being updated. Maybe I should contact Kenneth Reitz. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
How to get the needed version of a dependency
If I want to know the dependencies for requests I use: pip show requests And one of the lines I get is: Requires: certifi, charset-normalizer, idna, urllib3 But I want (in this case) to know with version of charset-normalizer requests needs. How do I get that? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Alan Bawden writes: > Cecil Westerhof writes: > >Yes, I try to select a random element, but it has also to be removed, >because an element should not be used more as once. > > Instead of using pop to do that why not something like: > > def lazy_shuffle(seq): > """ > Generate the elements of the given sequence in a random order. > """ > # Delete the next line if you want to use a different version of > # randrange: > from random import randrange > # Delete the next line if SEQ is already a mutable sequence and you > # are willing to have it destroyed by this process: > seq = list(seq) > n = len(seq) > while n: > i = randrange(n) > yield seq[i] > n -= 1 > if i < n: > seq[i] = seq[n] That looks interesting. But there is on problem. (I think.) The list is only partly eaten and I will eat a lot of sequences. So a lot of sequences will be left in the runtime. Or is there a way to destroy the lazy_shuffle when it is not needed anymore? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
MRAB writes: >>> When you pop an element from the last, the elements after it need to be >>> moved down, which takes time. >>> >>> Try shuffling the list and then popping the now randomly-ordered >>> elements off the end. >> Would shuffling not be a lot more expensive? Especially because I do >> not eat the whole list. >> > You won't know until you time it. A first indication is that it doubles the needed time. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Roel Schroeven writes: > Cecil Westerhof via Python-list schreef op 27/07/2022 om 17:43: >> "Michael F. Stemper" writes: >> >> > This is orthogonal to your question, but might be of some use to you: >> > >> > The combination of using len(to_try) as an argument to randint() and >> > saving the output to a variable named "index" suggests that you might >> > be setting up to select a random element from to_try, as in: >> > something = to_try[index] >> > >> > If that is the case, you might want to consider using random.choice() >> > instead: >> > >> > >>> from random import choice >> > >>> to_try = [2,3,5,7,11,13,"seventeen",19] >> > >>> choice(to_try) >> > 2 >> > >>> choice(to_try) >> > 'seventeen' >> > >>> choice(to_try) >> > 13 >> > >>> choice(to_try) >> > 5 >> > >>> >> >> Yes, I try to select a random element, but it has also to be removed, >> because an element should not be used more as once. >> This is the code I use: >> # index = randbelow(len(to_try)) >> index = randrange(len(to_try)) >> found = permutation[to_try.pop(index)] > Do you know in advance how many items you'll need, or maybe an upper > limit on the amount? In that case it might be more efficient to use > random.sample(to_try, k=nr_items_needed). Something else to try. :-) And yes: I will be using half of the list. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: More efficient code, but slower program
2qdxy4rzwzuui...@potatochowder.com writes: > On 2022-07-27 at 17:48:47 +0200, > Regarding "Re: More efficient code, but slower program," > Cecil Westerhof via Python-list wrote: > >> r...@zedat.fu-berlin.de (Stefan Ram) writes: >> >> > Cecil Westerhof writes: >> >>values = [*range(100)] >> > >> > In many cases, any iterable is just fine and a list is not >> > required, just as peudo-random numbers often are just fine and >> > real-world entropy is not required. >> >> In this case both are. I must select (several times) a random element >> from the list. So I need the list. >> I also want the randomness to be as good as possible to make the >> 'simulation' as good as possible. > > "[A]s good as possible" for simulations and tests may not require the > cryptographic quality numbers from SystemRandom. Many/most pseudo > random number generators are optimized for statistically normalized > outputs, and are repeatable as a bonus (again, often a requirement for > certain types of simulations; YMMV). > > Also, what if you shuffled the list first (e.g., with random.shuffle) > and then iterated through it directly? Repeatedly removing arbitrary > elements from the middle of a list is potentially expensive. Someone else also mentioned that. I think I should put it on my list of things to do/try. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
MRAB writes: > On 27/07/2022 16:43, Cecil Westerhof via Python-list wrote: >> "Michael F. Stemper" writes: >> >>> This is orthogonal to your question, but might be of some use to you: >>> >>> The combination of using len(to_try) as an argument to randint() and >>> saving the output to a variable named "index" suggests that you might >>> be setting up to select a random element from to_try, as in: >>> something = to_try[index] >>> >>> If that is the case, you might want to consider using random.choice() >>> instead: >>> >>> >>> from random import choice >>> >>> to_try = [2,3,5,7,11,13,"seventeen",19] >>> >>> choice(to_try) >>> 2 >>> >>> choice(to_try) >>> 'seventeen' >>> >>> choice(to_try) >>> 13 >>> >>> choice(to_try) >>> 5 >>> >>> >> Yes, I try to select a random element, but it has also to be removed, >> because an element should not be used more as once. >> This is the code I use: >> # index = randbelow(len(to_try)) >> index = randrange(len(to_try)) >> found = permutation[to_try.pop(index)] >> > > When you pop an element from the last, the elements after it need to be > moved down, which takes time. > > Try shuffling the list and then popping the now randomly-ordered > elements off the end. Would shuffling not be a lot more expensive? Especially because I do not eat the whole list. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Dennis Lee Bieber writes: > On Wed, 27 Jul 2022 10:45:47 +0200, Cecil Westerhof > declaimed the following: > > >>What do you mean with where the python version is from? > > Base Python.org download, ActiveState package download, Anaconda > package download, native OS install/extra install via OS repository > download (Debian/Ubuntu: apt install xxx, where xxx is not the native OS > Python) Just the default Debian install. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
More efficient code, but slower program
It is not very important, but I am just curious. Original I had in a program: values = [*range(100)] But because it is done quite often I expected that initialising: range_list = [*range(100)] and then use: values = range_list.copy() Would be more efficient. So I tried: timeit('values = [*range(100)]') 1.6964535564184189 and: timeit('new_values = values.copy()', 'values = [*range(100)]') 0.6457642465829849 That showed that it should make a positive difference. But when changing the program it took a little bit more time. I find the code with the copy a little bit better, so I kept it. But I am curious why the effect is the opposite of what I expected. It does not hurt to understand optimisation better, so I can do a better job when I need it. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Dennis Lee Bieber writes: > On Tue, 26 Jul 2022 23:47:59 +0200, Cecil Westerhof > declaimed the following: > > >>The new code: >>from random import SystemRandom >>system_random = SystemRandom() >>index = system_random.randint(0, len(to_try) - 1) >> >>The first two statements are executed once. >>The last statement I think about 75 * 10 ** 6. >> >>So it seems that my first idea of using randbelow was the correct one. >>But if anyone could explain why SystemRandom is so much more >>expensive, I would be interested to know it. >>(Or am I still doing something wrong?) > > What happens with > > system_randint = SystemRandom().randint #no parens > > index = system_randint(...) > > which may remove the method lookup from the repetition. I had already switched to randrange. This went to 15 minutes from 21 minutes. By removing the method lookup I could shave off another minute. So certainly noteworthy. (Should have thought about it myself.) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Chris Angelico writes: > Incidentally - if you are actually trying to select a specific item, > you may want to consider random.choice. Yes, I try to select a random element, but it has also to be removed. An element should be used at most once. This is the code I use: # index = randbelow(len(to_try)) index = randrange(len(to_try)) found = permutation[to_try.pop(index)] -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Chris Angelico writes: > On Wed, 27 Jul 2022 at 08:18, Cecil Westerhof via Python-list > wrote: >> >> Chris Angelico writes: >> >> > On Wed, 27 Jul 2022 at 06:06, Cecil Westerhof via Python-list >> > wrote: >> >> >> >> Chris Angelico writes: >> >> >> >> > On Wed, 27 Jul 2022 at 01:06, Cecil Westerhof via Python-list >> >> > wrote: >> >> >> >> >> >> I need to get a random integer. At first I tried it with: >> >> >> from secrets import randbelow >> >> >> index = randbelow(len(to_try)) >> >> >> >> >> >> This works perfectly, but it took some time. So I thought I try: >> >> >> from random import SystemRandom >> >> >> index = SystemRandom().randint(0, len(to_try) - 1) >> >> >> >> >> >> A first indication is that the second version would take about two >> >> >> times as much time as the first. Is there a reason for this, or should >> >> >> this not be happening? >> >> >> >> >> > >> >> > You're setting up a brand new SystemRandom instance just for a single >> >> > random number. For a fairer comparison, set up the instance, then >> >> > generate far more than just a single number, and see how that goes. >> >> >> >> Thanks. I thought I did something wrong and I did. >> >> I will try to implement like you said and look what the result will >> >> be. (And share it.) >> > >> > Thanks! Don't feel bad; performance testing is *hard*, getting >> > meaningful results takes a lot of of fiddling with parameters, and >> > getting interesting AND meaningful results can sometimes seem about >> > impossible. >> > >> >> (As I understand it both do more, or less the same and should have >> >> comparable performance.) >> > >> > In normal production work? Yes (the SystemRandom object doesn't have >> > any significant state - a seeded RNG could have a lot more overhead >> > here). But for performance testing? The work of instantiating the >> > class could be completely irrelevant, or it could be dominating your >> > results. It's hard to say, hence the suggestion to try it without >> > reinstantiating. >> >> It had a very big influence. Original it took about three times more >> time to run my program. (The program was still running when I posted >> the original post and the difference was higher as I anticipated.) >> Removing that did cut about 45% of the execution time of the program. >> (So the initiation is quit expensive.) >> But it still takes about 50% more time. So I am still a bit >> flabbergasted. >> >> The new code: >> from random import SystemRandom >> system_random = SystemRandom() >> index = system_random.randint(0, len(to_try) - 1) >> >> The first two statements are executed once. >> The last statement I think about 75 * 10 ** 6. >> >> So it seems that my first idea of using randbelow was the correct one. >> But if anyone could explain why SystemRandom is so much more >> expensive, I would be interested to know it. >> (Or am I still doing something wrong?) > > Hmm. There are still a lot of differences here. Are you able to make > use of randrange() instead, to make them more consistent? > > According to the source code, secrets.randbelow is calling on an > internal method _randbelow of the SystemRandom object, but randrange > (if called with only one arg) will go straight into that same method. > Here's my results: > > rosuav@sikorsky:~$ python3 -m timeit -s 'from random import randrange' > 'randrange(1)' > 100 loops, best of 5: 322 nsec per loop > rosuav@sikorsky:~$ python3 -m timeit -s 'from random import > SystemRandom; r = SystemRandom()' 'r.randint(0, 1)' > 20 loops, best of 5: 1.92 usec per loop > rosuav@sikorsky:~$ python3 -m timeit -s 'from random import > SystemRandom; r = SystemRandom()' 'r.randrange(1)' > 20 loops, best of 5: 1.87 usec per loop > rosuav@sikorsky:~$ python3 -m timeit -s 'from secrets import > randbelow' 'randbelow(1)' > 20 loops, best of 5: 1.64 usec per loop > > (The difference with the first one is that it isn't using the system > RNG, so it has the limitations of an internal PRNG.) > > When you call randint, what happens is (1) the endpoint is incremented > to transform it from inclusive-inclusive to inclusive-exclusive; (2)
Re: More efficient code, but slower program
r...@zedat.fu-berlin.de (Stefan Ram) writes: > Cecil Westerhof writes: >>values = [*range(100)] > > In many cases, any iterable is just fine and a list is not > required, just as peudo-random numbers often are just fine and > real-world entropy is not required. In this case both are. I must select (several times) a random element from the list. So I need the list. I also want the randomness to be as good as possible to make the 'simulation' as good as possible. > Usually one wants to write code for readability, and thinking > too much about runtime efficiency optimizations is in vain, > because one might get different results with a different > version of Python or on a different machine. That is why I went for the less efficient code. ;-) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Barry writes: >> On 26 Jul 2022, at 16:07, Cecil Westerhof via Python-list >> wrote: >> >> I need to get a random integer. At first I tried it with: >>from secrets import randbelow >>index = randbelow(len(to_try)) >> >> This works perfectly, but it took some time. So I thought I try: >>from random import SystemRandom >>index = SystemRandom().randint(0, len(to_try) - 1) >> >> A first indication is that the second version would take about two >> times as much time as the first. Is there a reason for this, or should >> this not be happening? > > What is the OS that you are running on and its version? > If it’s linux what is the kernel version? > What version of python and where from? That is always good information of-course. Debian 11.3 5.10.0-13-amd64 3.9.2 What do you mean with where the python version is from? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
"Michael F. Stemper" writes: > This is orthogonal to your question, but might be of some use to you: > > The combination of using len(to_try) as an argument to randint() and > saving the output to a variable named "index" suggests that you might > be setting up to select a random element from to_try, as in: > something = to_try[index] > > If that is the case, you might want to consider using random.choice() instead: > > >>> from random import choice > >>> to_try = [2,3,5,7,11,13,"seventeen",19] > >>> choice(to_try) > 2 > >>> choice(to_try) > 'seventeen' > >>> choice(to_try) > 13 > >>> choice(to_try) > 5 > >>> Yes, I try to select a random element, but it has also to be removed, because an element should not be used more as once. This is the code I use: # index = randbelow(len(to_try)) index = randrange(len(to_try)) found = permutation[to_try.pop(index)] -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Chris Angelico writes: > On Wed, 27 Jul 2022 at 06:06, Cecil Westerhof via Python-list > wrote: >> >> Chris Angelico writes: >> >> > On Wed, 27 Jul 2022 at 01:06, Cecil Westerhof via Python-list >> > wrote: >> >> >> >> I need to get a random integer. At first I tried it with: >> >> from secrets import randbelow >> >> index = randbelow(len(to_try)) >> >> >> >> This works perfectly, but it took some time. So I thought I try: >> >> from random import SystemRandom >> >> index = SystemRandom().randint(0, len(to_try) - 1) >> >> >> >> A first indication is that the second version would take about two >> >> times as much time as the first. Is there a reason for this, or should >> >> this not be happening? >> >> >> > >> > You're setting up a brand new SystemRandom instance just for a single >> > random number. For a fairer comparison, set up the instance, then >> > generate far more than just a single number, and see how that goes. >> >> Thanks. I thought I did something wrong and I did. >> I will try to implement like you said and look what the result will >> be. (And share it.) > > Thanks! Don't feel bad; performance testing is *hard*, getting > meaningful results takes a lot of of fiddling with parameters, and > getting interesting AND meaningful results can sometimes seem about > impossible. > >> (As I understand it both do more, or less the same and should have >> comparable performance.) > > In normal production work? Yes (the SystemRandom object doesn't have > any significant state - a seeded RNG could have a lot more overhead > here). But for performance testing? The work of instantiating the > class could be completely irrelevant, or it could be dominating your > results. It's hard to say, hence the suggestion to try it without > reinstantiating. It had a very big influence. Original it took about three times more time to run my program. (The program was still running when I posted the original post and the difference was higher as I anticipated.) Removing that did cut about 45% of the execution time of the program. (So the initiation is quit expensive.) But it still takes about 50% more time. So I am still a bit flabbergasted. The new code: from random import SystemRandom system_random = SystemRandom() index = system_random.randint(0, len(to_try) - 1) The first two statements are executed once. The last statement I think about 75 * 10 ** 6. So it seems that my first idea of using randbelow was the correct one. But if anyone could explain why SystemRandom is so much more expensive, I would be interested to know it. (Or am I still doing something wrong?) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: random.SystemRandom().randint() inefficient
Chris Angelico writes: > On Wed, 27 Jul 2022 at 01:06, Cecil Westerhof via Python-list > wrote: >> >> I need to get a random integer. At first I tried it with: >> from secrets import randbelow >> index = randbelow(len(to_try)) >> >> This works perfectly, but it took some time. So I thought I try: >> from random import SystemRandom >> index = SystemRandom().randint(0, len(to_try) - 1) >> >> A first indication is that the second version would take about two >> times as much time as the first. Is there a reason for this, or should >> this not be happening? >> > > You're setting up a brand new SystemRandom instance just for a single > random number. For a fairer comparison, set up the instance, then > generate far more than just a single number, and see how that goes. Thanks. I thought I did something wrong and I did. I will try to implement like you said and look what the result will be. (And share it.) (As I understand it both do more, or less the same and should have comparable performance.) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
random.SystemRandom().randint() inefficient
I need to get a random integer. At first I tried it with: from secrets import randbelow index = randbelow(len(to_try)) This works perfectly, but it took some time. So I thought I try: from random import SystemRandom index = SystemRandom().randint(0, len(to_try) - 1) A first indication is that the second version would take about two times as much time as the first. Is there a reason for this, or should this not be happening? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Functionality like local static in C
Thanks for the multiple answers. I was pleasantly surprised. I have something to think about. :-D In principle I selected a solution for the problem for which I asked it, but I first have to finish some other stuff. I hope to find time to implement it next week. Everyone a good weekend and Eastern. Cecil Westerhof writes: > In C when you declare a variable static in a function, the variable > retains its value between function calls. > The first time the function is called it has the default value (0 for > an int). > But when the function changes the value in a call (for example to 43), > the next time the function is called the variable does not have the > default value, but the value it had when the function returned. > Does python has something like that? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Functionality like local static in C
In C when you declare a variable static in a function, the variable retains its value between function calls. The first time the function is called it has the default value (0 for an int). But when the function changes the value in a call (for example to 43), the next time the function is called the variable does not have the default value, but the value it had when the function returned. Does python has something like that? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Sharing part of a function
Cecil Westerhof writes: > To show why it is often easy, but wrong to use recursive functions I > wrote the following two Fibonacci functions: > def fib_ite(n): > if not type(n) is int: > raise TypeError(f'Need an integer ({n})') > if n < 0: > raise ValueError(f'Should not be negative ({n})') > > if n in [0, 1]: > return n > > # a is previous fibonacy (starts with fib(0)) > # b is current fibonaccy (starts with fib(1)) > a, b = 0, 1 > # range goes to n - 1, so after loop b contains fib(n) > for i in range(1, n): > a, b = b, a + b > return b > > > def fib_rec(n): > if not type(n) is int: > raise TypeError(f'Need an integer ({n})') > if n < 0: > raise ValueError(f'Should not be negative ({n})') > > if n in [0, 1]: > return n > > return fib_rec(n - 2) + fib_rec(n - 1) > > The first eight lines are the same. And I did change the description > of the errors, which had to be done in both functions. What would be > the best way to circumvent this? > Two options are: > - Call an init function. > - Call the 'master' function with a lambda. > > What is the preferable way, or is there a better way? I have chosen this implementation with inner functions: def fibonacci(n, implementation = 'iterative'): def ite(n): # a is previous fibonacy (starts with fib(0)) # b is current fibonaccy (starts with fib(1)) a, b = 0, 1 # range goes to n - 1, so after loop b contains fib(n) for i in range(1, n): a, b = b, a + b return b def rec(n): if n in [0, 1]: return n return rec(n - 2) + rec(n - 1) if not type(n) is int: raise TypeError(f'Need an integer ({n})') if n < 0: raise ValueError(f'Should not be negative ({n})') if n in [0, 1]: return n if implementation == 'iterative': return ite(n) elif implementation == 'recursive': return rec(n) raise ValueError(f'Got a wrong function implementation type: {type}') -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Sharing part of a function
Betty Hollinshead writes: > "Memoising" is the answer -- see "Python Algorithms" by Magnus Lie Hetland. > In the mean time, here a simplified version of "memoising" using a dict. > This version handles pretty large fibonacci numbers! > > # fibonacci sequence > # memoised - but using a simple dictionary (see Python Algorithms, p177) > > memo= {} > memo[1] = 1 > memo[2] = 2 > > def fib(n): > if n in memo: > return memo[n] > else: > memo[n] = fib(n - 1) + fib(n - 2) > return memo[n] > > > print(100, fib(100)) > print(memo) No, it is not. It is the answer on a completely different question. Nice, but not what I was asking about. And there is even an error in the solution. By the way: it is better to do it iterative. Try (when not done a calculation before) fib(3_000). -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Suggestion for Linux Distro (from PSA: Linux vulnerability)
"Peter J. Holzer" writes: > On 2022-03-30 08:48:36 +0200, Marco Sulla wrote: >> On Tue, 29 Mar 2022 at 00:10, Peter J. Holzer wrote: >> > They are are about a year apart, so they will usually contain different >> > versions of most packages right from the start. So the Ubuntu and Debian >> > security teams probably can't benefit much from each other. >> >> Are you sure? Since LTS of Debian and Ubuntu lasts 5 years, I suppose >> the versions of the packages should overlap at some point in the past. > > Standard policy (there are exceptions) on most distros is to stay with > the same version of any package for the entire lifetime. So for example, > Ubuntu 20.04 was released with Apache 2.4.41 and Python 3.8.10 and > Debian 11 was released with Apache 2.4.53 and Python 3.9.2 and they are > still on these versions. Any security fixes and other critical bug fixes > were back-ported to these versions. Are you sure? In the past this was not the case, but it is possible that this has changed. (I do not really follow other distributions. I am quite happy with Debian.) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Temporally disabling buffering
In Python when the output of a script is going to a pipe stdout is buffered. When sending output to tee that is very inconvenient. We can set PYTHONUNBUFFERED, but then stdout is always unbuffered. On Linux we can do: PYTHONUNBUFFERED=T script.py | tee script.log Now the output is only unbuffered for the current run and buffered for other runs where the output goes to a pipe. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Suggestion for Linux Distro (from PSA: Linux vulnerability)
"Peter J. Holzer" writes: > On 2022-03-28 15:35:07 +0200, Cecil Westerhof via Python-list wrote: >> "Loris Bennett" writes: >> > Ubuntu is presumably relying on the Debian security team as well as >> > other volunteers and at least one company, namely Canonical. >> >> Nope. One important reason that I really hate that people use Ubuntu >> for servers is that Ubuntu wants to be up to date. > > Not sure what you mean by that. > > There is an Ubuntu LTS release every 2 years. There is also a Debian > release roughly every 2 years (although not on quite as strict a > schedule). So that's very similar. > >> So Ubuntu starts very close to Debian security wise, but will shift >> rapidly. > > They are are about a year apart, so they will usually contain different > versions of most packages right from the start. So the Ubuntu and Debian > security teams probably can't benefit much from each other. That is is what I partly mean. Debian is very big on security and stability. Most people think that Ubuntu is that also, because it is based on Debian. But Ubuntu wants also provide the newest versions of software and this will affect the stability and security negatively. Even for a desktop I find stability and security more important as the newest versions. That is why I even for the desktop use Debian. Personally I find it strange that people choose newest versions over stability and security for a server. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Suggestion for Linux Distro (from PSA: Linux vulnerability)
"Loris Bennett" writes: > Marco Sulla writes: > >> On Fri, 11 Mar 2022 at 19:10, Michael Torrie wrote: >>> Both Debian stable and Ubuntu LTS state they have a five year support >>> life cycle. >> >> Yes, but it seems that official security support in Debian ends after >> three years: >> >> "Debian LTS is not handled by the Debian security team, but by a >> separate group of volunteers and companies interested in making it a >> success" >> https://wiki.debian.org/LTS >> >> This is the only problem for me. > > I am not sure how different the two situations are. Ubuntu is > presumably relying on the Debian security team as well as other > volunteers and at least one company, namely Canonical. Nope. One important reason that I really hate that people use Ubuntu for servers is that Ubuntu wants to be up to date. So Ubuntu starts very close to Debian security wise, but will shift rapidly. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Openning Python program
Chris Angelico writes: > On Tue, 8 Feb 2022 at 06:51, Cecil Westerhof via Python-list > wrote: >> >> Chris Angelico writes: >> >> >> > How difficult would it be to get people to read those lines, though? >> >> >> >> That does remind me about a system administrator who wanted to make a >> >> point. He changed something on the server so all the Windows computers >> >> started up and gave a message: >> >> If you want to continue: click Cancel >> >> >> >> The help-desk became flooded with calls. I think he did a great job of >> >> showing a vulnerability. But it was not appreciated and he was fired. >> >> :'-( >> >> >> > >> > First image in this collection: >> > >> > https://thedailywtf.com/articles/How-Do-I-Use-This >> > >> > For those who can't click on links, it's a screenshot of a >> > confirmation dialogue. The user asked to cancel all the current >> > transfers, and the system wanted to check that the user really wanted >> > to do that; if you do indeed want to cancel those transfers, click >> > "Cancel", but if you actually don't want to, click "Cancel" instead. >> >> His dialog was crystal clear. The problem was that most users just >> click OK without reading the message. And that was what his little >> experiment showed. >> > > Ah. Yes, that... that sounds like a very familiar and serious vulnerability. I really think that always clicking on OK without ever checking what is going to happen is a problem. It at least shows that 'user friendly' software can be counter productive. >From long ago: Are you sure that you want to take this action? Yes. Are you really sure that you want to take this action? Yes. Are you really, really sure that you want to take this action. Yes. (With a curse under the breath.) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Openning Python program
Chris Angelico writes: >> > How difficult would it be to get people to read those lines, though? >> >> That does remind me about a system administrator who wanted to make a >> point. He changed something on the server so all the Windows computers >> started up and gave a message: >> If you want to continue: click Cancel >> >> The help-desk became flooded with calls. I think he did a great job of >> showing a vulnerability. But it was not appreciated and he was fired. >> :'-( >> > > First image in this collection: > > https://thedailywtf.com/articles/How-Do-I-Use-This > > For those who can't click on links, it's a screenshot of a > confirmation dialogue. The user asked to cancel all the current > transfers, and the system wanted to check that the user really wanted > to do that; if you do indeed want to cancel those transfers, click > "Cancel", but if you actually don't want to, click "Cancel" instead. His dialog was crystal clear. The problem was that most users just click OK without reading the message. And that was what his little experiment showed. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Openning Python program
Chris Angelico writes: > On Tue, 8 Feb 2022 at 02:53, Grant Edwards wrote: >> >> On 2022-02-06, Dennis Lee Bieber wrote: >> > On Sun, 6 Feb 2022 13:44:07 +0530, "createkmontalb...@gmail.com" >> > declaimed the following: >> > >> >> I cannot open python after downloading it keeps going to >> >> modify/uninstall >> >> ?? please help >> > >> > Stop clicking on the INSTALLER. What you downloaded is just the program >> > that installs and configures Python on your system. Stuff it away someplace >> > safe should you need to modify the current installation, but otherwise just >> > forget that it exists. >> >> This is _still_ a problem after all these years and countless >> identical complaints? >> >> How difficult would it be to add a few lines of text to the installer >> welcome screen explaining that you've just started the Python >> INSTALLER, and if you've already done the installation and want to >> "run Python" try ? >> > > How difficult would it be to get people to read those lines, though? That does remind me about a system administrator who wanted to make a point. He changed something on the server so all the Windows computers started up and gave a message: If you want to continue: click Cancel The help-desk became flooded with calls. I think he did a great job of showing a vulnerability. But it was not appreciated and he was fired. :'-( -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Chris Angelico writes: > On Sat, 5 Feb 2022 at 04:33, Cecil Westerhof via Python-list > wrote: >> >> Ethan Furman writes: >> >> > On 2/4/22 6:28 AM, Cecil Westerhof via Python-list wrote: >> > >> >> It was already not a good name, but I am rewriting the class >> >> completely, so now the name is a complete bumper. (No more timer.) I >> >> am thinking about naming the class repeating_thread, but I cannot say >> >> that I find it a very good name. So if someone has a good idea for a >> >> name … >> >> >> >> The class starts a thread where every by the user defined interval a >> >> by the user define function is called. >> > >> > How about `timed_repeat` or `repeat_timer`? >> >> timed_repeat does have something. >> > > What about "interval timer"? It is not really a timer, but on the other hand it seems to be a timer. (White box, black box.) I will add it. I do not have to decide before I publish the class, so I can let it simmer for a while. ;-) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
RuntimeError, or user defined exception
I am creating a class that will call a user defined function on user defined intervals. In my opinion it is an error when the function takes more as 10% of interval, or more as half a second. What is better: just using RuntimeError, or creating two exception classes for this? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Igor Berger writes: > On Friday, February 4, 2022 at 12:28:53 PM UTC-5, Cecil Westerhof wrote: >> Ethan Furman writes: >> >> > On 2/4/22 6:28 AM, Cecil Westerhof via Python-list wrote: >> > >> >> It was already not a good name, but I am rewriting the class >> >> completely, so now the name is a complete bumper. (No more timer.) I >> >> am thinking about naming the class repeating_thread, but I cannot say >> >> that I find it a very good name. So if someone has a good idea for a >> >> name … >> >> >> >> The class starts a thread where every by the user defined interval a >> >> by the user define function is called. >> > >> > How about `timed_repeat` or `repeat_timer`? >> timed_repeat does have something. > > run_periodically() ? Also better as mine. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Ethan Furman writes: > On 2/4/22 6:28 AM, Cecil Westerhof via Python-list wrote: > >> It was already not a good name, but I am rewriting the class >> completely, so now the name is a complete bumper. (No more timer.) I >> am thinking about naming the class repeating_thread, but I cannot say >> that I find it a very good name. So if someone has a good idea for a >> name … >> >> The class starts a thread where every by the user defined interval a >> by the user define function is called. > > How about `timed_repeat` or `repeat_timer`? timed_repeat does have something. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Cecil Westerhof writes: It was already not a good name, but I am rewriting the class completely, so now the name is a complete bumper. (No more timer.) I am thinking about naming the class repeating_thread, but I cannot say that I find it a very good name. So if someone has a good idea for a name … The class starts a thread where every by the user defined interval a by the user define function is called. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Barry writes: >> On 3 Feb 2022, at 04:45, Cecil Westerhof via Python-list >> wrote: >> >> Have to be careful that timing keeps correct when target takes a 'lot' >> of time. >> Something to ponder about, but can wait. > > You have noticed that your class does call the function at the repeat > interval but > rather at the repeat interval plus processing time. Nope: def _next(self): self._timer = Timer(self._interval, self._run) self._timer.start() def _run(self): self._next() self._fn() In _run I first set the new timer and then I execute the function. So that will go mostly OK. > The way to fix this is to subtract the last processing elapsed time for the > next interval. > Sort of a software phase locked loop. > > Just before you call the run function record the time.time() as start_time. > Then you can calculate next_interval = max( .001, interval - time.time() - > start_time) > I use 1ms as the min interval. But I am working on a complete rewrite to create a more efficient class. (This means I have to change also the code that uses it.) There I have to do something like you suggest. (I am already working on it.) Personally I am also of the opinion that the function should finish in less as 10% from the interval. (That was one of my rewrites.) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Chris Angelico writes: > On Thu, 3 Feb 2022 at 15:43, Cecil Westerhof via Python-list > wrote: >> >> Chris Angelico writes: >> >> >> > (Side point: The OP's code is quite inefficient, as it creates a new >> >> > thread for each reiteration, but there's nothing wrong with that if >> >> > you're looking for something simple.) >> >> >> >> It is just something I wrote fast. How could I do this in a better way? >> > >> > I'll answer your question, but first and foremost: Your code was fine, >> > and if something does what it's supposed to, that is the most >> > important. Everything else is minor. >> >> I like to write efficient code and it never hurts to write better code >> as just doing what it is supposed to do. ;-) >> >> And in my case interval is .5 seconds and when someone is going to use >> it with an even smaller interval … >> >> >> > But for other ways to do things, I would recommend creating a single >> > thread function and spawning a single thread to run it, and then >> > having that function call the target every N seconds. Also, consider >> >> Have to be careful that timing keeps correct when target takes a 'lot' >> of time. >> Something to ponder about, but can wait. > > Ah. In that case, I would recommend a different look at things. > Instead of waiting X time, then firing the event, then waiting X time, > consider instead an interval timer based on monotonic time: > > https://docs.python.org/3/library/time.html#time.monotonic > > When the timer starts, record the current monotonic time, and sleep > one interval. After the function returns, sleep the remainder of one > interval. It's up to you what happens if you ever find that the next > time point has already passed - do you call the function immediately, > or skip and wait for the next moment? > > Interval timers have some complexity to them, but it's worth putting > in the time (pun intended) to figure out how these things work :) I will look into it. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Cecil Westerhof writes: > I need (sometimes) to repeatedly execute a function. For this I wrote > the below class. What do you think about it? I wrote some unit test for the class. Is this the correct way to do this? For example in test_correct_params_no_start I check four things. Some people say you should not check more as one. By the way it was good that I defined __enter__ and __exit__. :-D #!/usr/bin/env python3 import unittest from threading import Timer from repeated_timer import repeated_timer class test_repeated_timer(unittest.TestCase): def test_interval_zero(self): with self.assertRaises(ValueError): rt = repeated_timer(dummy_fn, 0) def test_interval_negative(self): with self.assertRaises(ValueError): rt = repeated_timer(dummy_fn, -1) def test_interval_string(self): with self.assertRaises(TypeError): rt = repeated_timer(dummy_fn, '.4') def test_non_function(self): with self.assertRaises(TypeError): rt = repeated_timer('dummy_fn', .5) def test_correct_params_no_start(self): rt = repeated_timer(dummy_fn, .5) self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .5) self.assertEqual(rt._timer,None) self.assertFalse(rt._is_running) def test_correct_params_do_start(self): with repeated_timer(dummy_fn, .375, True) as rt: self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .375) self.assertTrue (isinstance(rt._timer, Timer), 'There should be a timer') self.assertTrue (rt._is_running, 'Should be running') def test__start_later(self): with repeated_timer(dummy_fn, .5) as rt: self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .5) self.assertEqual(rt._timer,None) self.assertFalse(rt._is_running) rt.start() self.assertEqual(rt._fn, dummy_fn) self.assertEqual(rt._interval, .5) self.assertTrue (isinstance(rt._timer, Timer), 'There should be a timer') self.assertTrue (rt._is_running, 'Should be running') def dummy_fn(): pass if __name__ == '__main__': unittest.main() > from threading import Timer > > > > class repeated_timer(object): > def __init__(self, fn, interval, start = False): > if not callable(fn): > raise TypeError('{} is not a function'.format(fn)) > self._fn = fn > self._check_interval(interval) > self._interval = interval > self._timer = None > self._is_running = False > if start: > self.start() > > def _check_interval(self, interval): > if not type(interval) in [int, float]: > raise TypeError('{} is not numeric'.format(interval)) > if interval <= 0: > raise ValueError('{} is not greater as 0'.format(interval)) > > def _next(self): > self._timer = Timer(self._interval, self._run) > self._timer.start() > > def _run(self): > self._next() > self._fn() > > def set_interval(self, interval): > self._check_interval(interval) > self._interval = interval > > def start(self): > if not self._is_running: > self._next() > self._is_running = True > > def stop(self): > if self._is_running: > self._timer.cancel() > self._timer = None > self._is_running = False -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
2qdxy4rzwzuui...@potatochowder.com writes: > FWIW, I'd find some way to tell users the units (seconds, milliseconds, > fortnights, etc.) instead of making them wade through your code to find > the call to (and possibly the [broken] help text of) Timer. You mean with docstring? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Chris Angelico writes: >> > (Side point: The OP's code is quite inefficient, as it creates a new >> > thread for each reiteration, but there's nothing wrong with that if >> > you're looking for something simple.) >> >> It is just something I wrote fast. How could I do this in a better way? > > I'll answer your question, but first and foremost: Your code was fine, > and if something does what it's supposed to, that is the most > important. Everything else is minor. I like to write efficient code and it never hurts to write better code as just doing what it is supposed to do. ;-) And in my case interval is .5 seconds and when someone is going to use it with an even smaller interval … > But for other ways to do things, I would recommend creating a single > thread function and spawning a single thread to run it, and then > having that function call the target every N seconds. Also, consider Have to be careful that timing keeps correct when target takes a 'lot' of time. Something to ponder about, but can wait. > subclassing Thread rather than subclassing object (which, btw, is the > default; you don't need to say "class X(object)"), which will > automatically give your object all the methods of a timer. Of-course. I should have thought about that. :'-( -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Cameron Simpson writes: > You have: > > def _check_interval(self, interval): > if not type(interval) in [int, float]: > raise TypeError('{} is not numeric'.format(interval)) > > This check is better written: > > if not isinstance(interval, (int,float)): > > which handles subclasses of these types (but note that bool subclasses > int :-) Done, thanks. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Cecil Westerhof writes: >> (regardless of your OS). The same could be done with this timer; an >> __exit__ method would make a lot of sense here, and would allow the >> timer to be used in a with block to govern its execution. (It also >> isn't really necessary, but if you want a good Pythonic way to show >> the beginning and end of its use area, a 'with' block is the way to >> go.) > > I will look into that. Implemented: from threading import Timer class repeated_timer(object): def __init__(self, fn, interval, start = False): if not callable(fn): raise TypeError('{} is not a function'.format(fn)) self._fn = fn self._check_interval(interval) self._interval = interval self._timer = None self._is_running = False if start: self.start() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.stop() def _check_interval(self, interval): if not type(interval) in [int, float]: raise TypeError('{} is not numeric'.format(interval)) if interval <= 0: raise ValueError('{} is not greater as 0'.format(interval)) def _next(self): self._timer = Timer(self._interval, self._run) self._timer.start() def _run(self): self._next() self._fn() def set_interval(self, interval): self._check_interval(interval) self._interval = interval def start(self): if not self._is_running: self._is_running = True self._next() def stop(self): if self._is_running: self._timer.cancel() self._timer = None self._is_running = False -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Waht do you think about my repeated_timer class
Chris Angelico writes: > On Thu, 3 Feb 2022 at 09:33, Barry wrote: > (Side point: The OP's code is quite inefficient, as it creates a new > thread for each reiteration, but there's nothing wrong with that if > you're looking for something simple.) It is just something I wrote fast. How could I do this in a better way? > (regardless of your OS). The same could be done with this timer; an > __exit__ method would make a lot of sense here, and would allow the > timer to be used in a with block to govern its execution. (It also > isn't really necessary, but if you want a good Pythonic way to show > the beginning and end of its use area, a 'with' block is the way to > go.) I will look into that. -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Waht do you think about my repeated_timer class
I need (sometimes) to repeatedly execute a function. For this I wrote the below class. What do you think about it? from threading import Timer class repeated_timer(object): def __init__(self, fn, interval, start = False): if not callable(fn): raise TypeError('{} is not a function'.format(fn)) self._fn = fn self._check_interval(interval) self._interval = interval self._timer = None self._is_running = False if start: self.start() def _check_interval(self, interval): if not type(interval) in [int, float]: raise TypeError('{} is not numeric'.format(interval)) if interval <= 0: raise ValueError('{} is not greater as 0'.format(interval)) def _next(self): self._timer = Timer(self._interval, self._run) self._timer.start() def _run(self): self._next() self._fn() def set_interval(self, interval): self._check_interval(interval) self._interval = interval def start(self): if not self._is_running: self._next() self._is_running = True def stop(self): if self._is_running: self._timer.cancel() self._timer = None self._is_running = False -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Re: Big jump in version
Grant Edwards writes: > On 2021-10-04, Cecil Westerhof via Python-list wrote: >> When I run: >> pip3 list --outdated >> >> I get: >> Package Version Latest Type >> --- -- - >> cryptography 3.4.8 35.0.0 wheel >> >> The jump from 3 to 35 seems a bit excessive to me. Or is it correct? > > https://cryptography.io/en/latest/changelog/ Thanks, that takes away my doubts. ;-) Y always being 0 seems strange to me. But who am I to complain? '-) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Big jump in version
When I run: pip3 list --outdated I get: Package Version Latest Type --- -- - cryptography 3.4.8 35.0.0 wheel pyzstd 0.14.4 0.15.0 wheel The jump from 3 to 35 seems a bit excessive to me. Or is it correct? On a side node. I have not updated pyzstd for a long time, because that breaks py7zr which needs a version lower as 0.15.0. Any chance that py7zr is going to be updated? -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list
Cannot update parso
I cannot update parso because of the rule from jedi: <0.8.0,>=0.7.0 This kind of things happens more often, but normally in less of a week the module that prevents another to be installed is updated and the restriction is lifted. But I think it is about half a year that this restriction is active. Why is jedi not updated. (I cannot uninstall jedi, because it is used by ipython.) -- Cecil Westerhof Senior Software Engineer LinkedIn: http://www.linkedin.com/in/cecilwesterhof -- https://mail.python.org/mailman/listinfo/python-list