Re: Single line if statement with a continue

2022-12-15 Thread Cecil Westerhof via Python-list
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

2022-12-14 Thread Cecil Westerhof via Python-list
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

2022-12-14 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
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

2022-07-27 Thread Cecil Westerhof via Python-list
"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

2022-07-26 Thread Cecil Westerhof via Python-list
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

2022-07-26 Thread Cecil Westerhof via Python-list
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

2022-07-26 Thread Cecil Westerhof via Python-list
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

2022-04-15 Thread Cecil Westerhof via Python-list
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

2022-04-14 Thread Cecil Westerhof via Python-list
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

2022-04-07 Thread Cecil Westerhof via Python-list
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

2022-04-03 Thread Cecil Westerhof via Python-list
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)

2022-03-31 Thread Cecil Westerhof via Python-list
"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

2022-03-31 Thread Cecil Westerhof via Python-list
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)

2022-03-31 Thread Cecil Westerhof via Python-list
"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)

2022-03-28 Thread Cecil Westerhof via Python-list
"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

2022-02-08 Thread Cecil Westerhof via Python-list
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

2022-02-07 Thread Cecil Westerhof via Python-list
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

2022-02-07 Thread Cecil Westerhof via Python-list
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

2022-02-04 Thread Cecil Westerhof via Python-list
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

2022-02-04 Thread Cecil Westerhof via Python-list
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

2022-02-04 Thread Cecil Westerhof via Python-list
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

2022-02-04 Thread Cecil Westerhof via Python-list
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

2022-02-04 Thread Cecil Westerhof via Python-list
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

2022-02-03 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2022-02-02 Thread Cecil Westerhof via Python-list
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

2021-10-07 Thread Cecil Westerhof via Python-list
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

2021-10-05 Thread Cecil Westerhof via Python-list
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

2020-11-21 Thread Cecil Westerhof via Python-list
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