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


Re: Why does super(bool) give None

2020-04-24 Thread Cecil Westerhof
Cecil Westerhof  writes:

>> I've never actually looked at the repr of a super object - I've always
>> just called a method on it immediately after constructing it. Never
>> seen a need to hang onto one :)
>
> Well, maybe I will never need it, but I am just curious. And sometimes
> it was very handy that I had sought out 'useless' things.

You can get the information with the inspect module (done with
ipython3):
In [1]: import inspect

In [2]: inspect.getmro(bool)
Out[2]: (bool, int, object)

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Why does super(bool) give None

2020-04-24 Thread Cecil Westerhof
Chris Angelico  writes:

> On Fri, Apr 24, 2020 at 4:16 PM Cecil Westerhof  wrote:
>>
>> issubclass(bool, int) gives True
>> but
>> super(bool) gives 
>>
>> Do I not understand the meaning of super, or is this inconsistent?
>>
>> (Until now I have not down much work with classes in Python.)
>>
>
> One-arg super is an unbound object, and the "None" just indicates
> that. (Although every Python that I've tried says NULL there, not
> None. What version are you using?)

That was because I was using ipython3, python does what you expect:
Python 3.7.3 (default, Dec 20 2019, 18:57:59)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> super(bool)
, NULL>


When using ipython3 it goes like:
Python 3.7.3 (default, Dec 20 2019, 18:57:59)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: super(bool)
Out[1]: 



> It doesn't say what "the parent class" is, because super doesn't
> actually work with parent classes - it lets you call the *next*
> class. (In complex inheritance trees, that can mean going across a
> diamond or anything.)

I have more learning to do as I tought. ;-)


> I've never actually looked at the repr of a super object - I've always
> just called a method on it immediately after constructing it. Never
> seen a need to hang onto one :)

Well, maybe I will never need it, but I am just curious. And sometimes
it was very handy that I had sought out 'useless' things.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Why does super(bool) give None

2020-04-24 Thread Cecil Westerhof
issubclass(bool, int) gives True
but
super(bool) gives 

Do I not understand the meaning of super, or is this inconsistent?

(Until now I have not down much work with classes in Python.)

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What about idea of making a "Pythonic Lisp"...i.e. a Lisp that more closely resembles the syntax of Python?

2019-09-19 Thread Cecil Westerhof
Paul Rubin  writes:

> Python 3.7.3 (default, Apr  3 2019, 05:39:12)
> Type "help", "copyright", "credits" or "license" for more information.
> >>> a = range(10)
> >>> b = reversed(a)
> >>> sum(a) == sum(b)
> True
> >>> sum(b) == sum(a)
> False

Why does this happen?

By the way, when you change the last statement to:
sum(a) == sum(b)

you also get False.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Use global, or not

2019-06-29 Thread Cecil Westerhof
DL Neil  writes:

> On 29/06/19 1:44 AM, Cecil Westerhof wrote:
>> I have written a GUI program where I have quit a few global variables.
>> I did not like this, so I now use one global dict. Something like:
>>  global global_dict
> ...
>
>> Is that an acceptable way to do this?
>
>
> If it works, isn't that the largest part of "acceptable"?

Depends on your way of thinking. ;-)
I think it is always best when you write in a language to do it in
that languages way. In this case Python.
I also think this is a program that could be interesting to share.
Then it becomes even more important to do it the Python way.
And my experience is that when asking this type of question you often
get a tip that helps you make your program better.


> In each case, (previously discussed and/or below) you are taking
> advantage of "namespaces" to keep one 'lot' of values separated and
> distinct from others - as well as finding a means of 'passing them
> around'. The other half of the considerations is how the values are
> being retrieved/utilised within the mainline code.
>
> An alternative might be to use a class. Then accessing a single value
> becomes instance.attribute, but when you have need for several
> attribute's values or to compute a value from several attributes, an
> instance.method() may simplify things.

That was the other possibility I was thinking about. And that would be
maybe better. Because I now do things like:
global_dict['messages']['created'].format(len(filepathArr))

much better would be:
instance.created(len(filepathArr))

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Use global, or not

2019-06-28 Thread Cecil Westerhof
I have written a GUI program where I have quit a few global variables.
I did not like this, so I now use one global dict. Something like:
global global_dict

canceled_report  = 'Genereren rapportage gecanceled.'
created_report   = 'Rapportage voor {} bestanden is gemaakt.'
error_append = 'Er ging iets fout bij het toevoegen van een record.'
error_generate   = 'Er ging iets fout bij het genereren van de 
rapportage.'
error_select = 'Er ging iets fout bij het selecteren van de 
directory.'
error_widening   = 'Er ging iets fout bij instellen van de wijdte.'
error_nofiles= 'Er zijn geen bestanden om te verwerken.'
messages = {
'canceled': canceled_report,
'created':  created_report,
'append':   error_append,
'generate': error_generate,
'select':   error_select,
'widening': error_widening,
'nofiles':  error_nofiles,
}
error_str   = 'Foutmelding'
info_str= 'Info'
warning_str = 'Waarschuwing'
titles  = {
'error':   error_str,
'info':info_str,
'warning': warning_str,
}
.
.
.
window = Tk()
.
.
.
progress   = ttk.Progressbar(progress_frame, orient = 'horizontal',
 length = 200, mode = 'determinate')
.
.
.
global_dict  = {
'messages': messages,
'progress': progress,
'window':   window,
}

And in the program do things like:
global_dict['progress']['value'] += 1
global_dict['window'].update_idletasks()
global_dict['window'].update_idletasks()

and:
messagebox.showwarning(global_dict['titles']['warning'],
   global_dict['messages']['nofiles'])


Is that an acceptable way to do this?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Only a message at the highest exception

2019-06-28 Thread Cecil Westerhof
Cameron Simpson  writes:

> On 28Jun2019 12:17, Cecil Westerhof  wrote:
>>Chris Angelico  writes:
>>> On Fri, Jun 28, 2019 at 7:33 PM Cecil Westerhof  wrote:
>>>> I have a tkinter program where I have a function generate_report
>>>> which
>>>> in a try block calls the function append_row. This function has also a
>>>> try block. When they get an exception they give message. But when
>>>> append_row has already given a message then generate_report should
>>>> not. To implement this I use the following class:
>>>>
>>>> class AlreadyHandledException(Exception):
>>>> pass
>>>>
>>>> Then in append_row I have:
>>>> except Exception as err:
>>>> messagebox.showerror(error_str,
>>>>  error_append + '\n\n\n\n' + str(err))
>>>> raise AlreadyHandledException()
>>>>
>>>> And in generate_report I have:
>>>> except Exception as err:
>>>> if type(err).__name__ != "AlreadyHandledException":
>>>> messagebox.showerror(error_str,
>>>>  error_generate + '\n\n\n\n' + str(err))
>>>> progress.pack_forget()
>>>>
>>>> Is this an acceptable way, or should I do it differently?
>>>
>>> Well, first off, I would use two separate except clauses, rather than
>>> a type check.
>>
>>You are completely right.
>>
>>> But are you able to just NOT catch the exception inside
>>> append_row? Let it be handled at the top level only.
>>
>>I am giving different messages. I changed the top part to:
>>except AlreadyHandledException:
>>pass
>>except Exception as err:
>>messagebox.showerror(error_str, error_generate + '\n\n\n\n' + 
>> str(err))
>>progress.lower()
>
> For contrast, another approach.
>
> By catching AlreadyHandledException and just going "pass" you're
> effectively swalling that exception. For your purpose, that works.
>
> However, in a since, why raise an exception you _know_ you're going to
> deliberately ignore?

I am not. I am using it to quit generating the report. Just ignoring
that I could not append a record does not sound correct to me. Yes
they got a message that something went wrong. But if there is still a
generated report, things will go wrong.


> What if you have append_row return a Boolean? True on success, False on
> failure but situation handled (i.e. append_row has shown an error, or
> whatever recovery you adopt). And keep the uncaught exceptions for the
> _unhandled_ situation. The "exceptional" situation.
>
> Example:
>
>  def append_row(...):
>  ...
>  try:
>      ...stuff...
>  except ExpectedExceptionHere as err:
>  messagebox.showerror()
>  ...maybe some cleanup...
>  return False
>  ...
>  return True
>
> Then your generate_report code goes:
>
>try:
>appended = append_row()
>except Exception as err:
>messagebox.showerror()
>else:
>if appended:
>hooray!
>else:
>unhappy, but continuing

And that is exactly what I not want to do.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Only a message at the highest exception

2019-06-28 Thread Cecil Westerhof
Chris Angelico  writes:

> On Fri, Jun 28, 2019 at 7:33 PM Cecil Westerhof  wrote:
>>
>> I have a tkinter program where I have a function generate_report which
>> in a try block calls the function append_row. This function has also a
>> try block. When they get an exception they give message. But when
>> append_row has already given a message then generate_report should
>> not. To implement this I use the following class:
>> class AlreadyHandledException(Exception):
>> pass
>>
>> Then in append_row I have:
>> except Exception as err:
>> messagebox.showerror(error_str,
>>  error_append + '\n\n\n\n' + str(err))
>> raise AlreadyHandledException()
>>
>> And in generate_report I have:
>> except Exception as err:
>> if type(err).__name__ != "AlreadyHandledException":
>> messagebox.showerror(error_str,
>>  error_generate + '\n\n\n\n' + str(err))
>> progress.pack_forget()
>>
>> Is this an acceptable way, or should I do it differently?
>>
>
> Well, first off, I would use two separate except clauses, rather than
> a type check.

You are completely right.


> But are you able to just NOT catch the exception inside
> append_row? Let it be handled at the top level only.

I am giving different messages. I changed the top part to:
except AlreadyHandledException:
pass
except Exception as err:
messagebox.showerror(error_str, error_generate + '\n\n\n\n' + str(err))
progress.lower()

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Hiding a progressbar in tkinter

2019-06-28 Thread Cecil Westerhof
MRAB  writes:

> On 2019-06-26 16:47, Cecil Westerhof wrote:
>> I just started with GUI stuff in tkinter. I have a progressbar, but I
>> want it to be only visible when it is used. So I tried the following:
>>  window = Tk()
>>  window.title(window_str)
>>  frame  = Frame(window)
>>  frame.pack(side = "top", fill = "both", expand = True)
>>  Button(window, text = button_str, command = select_dir).pack()
>>  progress = ttk.Progressbar(window, orient = "horizontal", length = 200,
>> mode = "determinate")
>>  progress.pack()
>>  progress.lower(frame)
>>  window.mainloop()
>>
>> But that does not hide the progressbar. What am I doing wrong?
>>
>> I could use pack_forget, but that will change the dimensions of the
>> window.
>>
> The progress bar isn't hidden because there's nothing on top of it to
> hide it.
>
> import tkinter as tk
> import tkinter.ttk as ttk
>
> window = tk.Tk()
> window.title(window_str)
> frame = tk.Frame(window)
> frame.pack(side='top', fill='both', expand=True)
> tk.Button(window, text=button_str, command=select_dir).pack()
>
> # Create a frame to hold the progress bar.
> progress_frame = tk.Frame(window)
> progress_frame.pack(fill='x', expand=True)
>
> # Put the progress bar into the progress frame, ensuring that it fills
> the grid cell.
> progress = ttk.Progressbar(progress_frame, orient='horizontal',
> length=200, mode='determinate')
> progress.grid(row=0, column=0, sticky='nsew')
>
> # Now put a blank frame into the progress frame over the progress bar,
> ensuring that it fills the same grid cell.
> blank = tk.Frame(progress_frame)
> blank.grid(row=0, column=0, sticky='nsew')
>
> # Raise the progress bar over the blank frame to reveal it.
> progress.tkraise()
>
> # Lower the progress bar underneath the blank frame to hide it.
> progress.lower()
>
> window.mainloop()

Works like a charm. Thanks.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Only a message at the highest exception

2019-06-28 Thread Cecil Westerhof
I have a tkinter program where I have a function generate_report which
in a try block calls the function append_row. This function has also a
try block. When they get an exception they give message. But when
append_row has already given a message then generate_report should
not. To implement this I use the following class:
class AlreadyHandledException(Exception):
pass

Then in append_row I have:
except Exception as err:
messagebox.showerror(error_str,
 error_append + '\n\n\n\n' + str(err))
raise AlreadyHandledException()

And in generate_report I have:
except Exception as err:
if type(err).__name__ != "AlreadyHandledException":
messagebox.showerror(error_str,
 error_generate + '\n\n\n\n' + str(err))
progress.pack_forget()

Is this an acceptable way, or should I do it differently?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Creating a Windows executable on a Linux system

2019-06-28 Thread Cecil Westerhof
Cecil Westerhof  writes:

> Cecil Westerhof  writes:
>
>> I need to write a Python desktop program. I create it on a Linux
>> system, but it has to run on a Windows system. When looking at how to
>> create an executable it seems that you need to be on a Windows system
>> to create a Windows executable. Is this true, or is it possible to
>> create a Windows executable on a Linux system?
>>
>> Any pointers about best practice creating a standalone executable are
>> welcome.
>
> For the moment it is not a problem.
> It is allowed to install Python openpyxl on the systems

Oops, that should have been:
It is allowed to install Python AND openpyxl on the systems


> where this application has to run. Letting the
> application name end on pyw and put a link on the desktop makes it
> work for the people that need to work with it.
>
> Still interested in getting it to work (for when I get in the
> situation that I have to distribute a Python program where it is not
> allowed to install Python), but it is not urgent anymore.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Copying a row from a range of Excel files to another

2019-06-28 Thread Cecil Westerhof
MRAB  writes:

> On 2019-06-26 22:14, Cecil Westerhof wrote:
>> MRAB  writes:
>>
>>> Does Workbook support the 'with' statement?
>>>
>>> If it does, then that's the best way of doing it.
>>>
>>> (Untested)
>>>
>>> with Workbook() as wb_out:
>>> for filepath in filepathArr:
>>> current_row = []
>>>
>>> with load_workbook(filepath) as wb_in:
>>> for cell in wb_in.active[src_row]:
>>> current_row.append(cell.value)
>>>
>>> wb_out.active.append(current_row)
>>>
>>> wb_out.save(report_start + datetime.now().strftime('%Y-%m-%d') +
>>> report_end)
>>
>> It seems not. I get AttributeError.
>>
> You didn't say which line.

I made a minimalist program to show it:
#!/usr/bin/env python3


from openpyxl import Workbook


with Workbook() as wb_out:
print('In loop')
print('After loop')

This results in:
Traceback (most recent call last):
  File "./test.py", line 7, in 
with Workbook() as wb_out:
AttributeError: __exit__


> Anyway, if Workbooks are closed using a method called "close", you can
> wrap them in a "closing" context manager:

That seems to work. I changed it to:
#!/usr/bin/env python3


from contextlib   import closing
from datetime import datetime
from openpyxl import Workbook


with closing(Workbook()) as wb_out:
print('In loop')
wb_out.save('testing_' + datetime.now().strftime('%Y-%m-%d') + '.xlsx')
print('After loop')

And I see:
In loop
After loop

And a testing Excel file.

Thanks.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Creating a Windows executable on a Linux system

2019-06-28 Thread Cecil Westerhof
Cecil Westerhof  writes:

> I need to write a Python desktop program. I create it on a Linux
> system, but it has to run on a Windows system. When looking at how to
> create an executable it seems that you need to be on a Windows system
> to create a Windows executable. Is this true, or is it possible to
> create a Windows executable on a Linux system?
>
> Any pointers about best practice creating a standalone executable are
> welcome.

For the moment it is not a problem. It is allowed to install Python
openpyxl on the systems where this application has to run. Letting the
application name end on pyw and put a link on the desktop makes it
work for the people that need to work with it.

Still interested in getting it to work (for when I get in the
situation that I have to distribute a Python program where it is not
allowed to install Python), but it is not urgent anymore.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Make sure the window title is visible in tkinter

2019-06-28 Thread Cecil Westerhof
Cecil Westerhof  writes:

> Wildman  writes:
>
>> On Wed, 26 Jun 2019 13:25:15 +0200, Cecil Westerhof wrote:
>>
>>> I need to write a desktop program. I choose to use tkinter. How can I
>>> make sure the window title is visible? For example when I have the
>>> following code:
>>> from tkinter  import Button, filedialog, Label, messagebox, Tk
>>> 
>>> 
>>> window = Tk()
>>> window.title('A long window title')
>>> Button (window, text = 'Short text').pack()
>>> window.mainloop()
>>> 
>>> I see only a part of the 'A', but I would like to see the complete:
>>> 'A long window title'
>>
>> According to link below, it is not possible...
>> "Tkinter has no way of knowing how long the title is on the titlebar."
>>
>> https://stackoverflow.com/questions/35273690/tkinter-window-not-wide-enough-to-display-window-title
>
> OK, then I will have to live with it.

I just make sure something is in my window that has such a width that
the tittle will be displayed. ;-)

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Copying a row from a range of Excel files to another

2019-06-26 Thread Cecil Westerhof
MRAB  writes:

> Does Workbook support the 'with' statement?
>
> If it does, then that's the best way of doing it.
>
> (Untested)
>
> with Workbook() as wb_out:
> for filepath in filepathArr:
> current_row = []
>
> with load_workbook(filepath) as wb_in:
> for cell in wb_in.active[src_row]:
> current_row.append(cell.value)
>
> wb_out.active.append(current_row)
>
> wb_out.save(report_start + datetime.now().strftime('%Y-%m-%d') +
> report_end)

It seems not. I get AttributeError.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Hiding a progressbar in tkinter

2019-06-26 Thread Cecil Westerhof
I just started with GUI stuff in tkinter. I have a progressbar, but I
want it to be only visible when it is used. So I tried the following:
window = Tk()
window.title(window_str)
frame  = Frame(window)
frame.pack(side = "top", fill = "both", expand = True)
Button(window, text = button_str, command = select_dir).pack()
progress = ttk.Progressbar(window, orient = "horizontal", length = 200,
   mode = "determinate")
progress.pack()
progress.lower(frame)
window.mainloop()

But that does not hide the progressbar. What am I doing wrong?

I could use pack_forget, but that will change the dimensions of the
window.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Make sure the window title is visible in tkinter

2019-06-26 Thread Cecil Westerhof
Wildman  writes:

> On Wed, 26 Jun 2019 13:25:15 +0200, Cecil Westerhof wrote:
>
>> I need to write a desktop program. I choose to use tkinter. How can I
>> make sure the window title is visible? For example when I have the
>> following code:
>> from tkinter  import Button, filedialog, Label, messagebox, Tk
>> 
>> 
>> window = Tk()
>> window.title('A long window title')
>> Button (window, text = 'Short text').pack()
>> window.mainloop()
>> 
>> I see only a part of the 'A', but I would like to see the complete:
>> 'A long window title'
>
> According to link below, it is not possible...
> "Tkinter has no way of knowing how long the title is on the titlebar."
>
> https://stackoverflow.com/questions/35273690/tkinter-window-not-wide-enough-to-display-window-title

OK, then I will have to live with it.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Copying a row from a range of Excel files to another

2019-06-26 Thread Cecil Westerhof
Cecil Westerhof  writes:

> Is it necessary to close the workbooks to circumvent a resource
> leak?

Still like to know. When not necessary it is better not to cloes them
I think.


> Is it a problem when a workbook is closed two times? If so I need to
> make sure that this is not possible.

That is not a problem. I tried it and it just works.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Creating a Windows executable on a Linux system

2019-06-26 Thread Cecil Westerhof
"Peter Heitzer"  writes:

> Cecil Westerhof  wrote:
>>I need to write a Python desktop program. I create it on a Linux
>>system, but it has to run on a Windows system. When looking at how to
>>create an executable it seems that you need to be on a Windows system
>>to create a Windows executable. Is this true, or is it possible to
>>create a Windows executable on a Linux system?
>
>>Any pointers about best practice creating a standalone executable are
>>welcome.
> Is using a portable Python installation an option?

That is not supported anymore. But they pointed to WinPython. I will
look into that/ One important thing is that the application uses
openpyxl and tkinter.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Copying a row from a range of Excel files to another

2019-06-26 Thread Cecil Westerhof
Cecil Westerhof  writes:

> I was asked to copy a certain line from about 300 Excel lines to a new
> Excel file. That is not something I would like to do by hand and I
> immediately thought: that should be possible with Python.
>
> And it is. I was surprised how fast I could write that with openpyxl.
> My first try was not very neat, but a proof of concept. Then by
> looking better at the possibilities I could get much cleaner code. But
> I am still not completely happy. At the moment I have the following
> code:
> wb_out = Workbook()
> for filepath in filepathArr:
> current_row = []
> wb_in   = load_workbook(filepath)
> for cell in wb_in.active[src_row]:
> current_row.append(cell.value)
> wb_out.active.append(current_row)
> wb_in.close()
> wb_out.save(report_start + datetime.now().strftime('%Y-%m-%d') + 
> report_end)
> wb_out.close()
>
> I could not find a way to copy a row from one workbook to another.
> That is why I put the row in current_row and do an append. Am I
> overlooking something, or is that really the way to do this?
>
>
> I am not used to writing GUI programs. (I have to learn tkinter also.)
> What is the best way to handle potential errors? It could go wrong on
> line 1, 4, 5, 7, 8, 9 and 10. Should I catch every exception alone, or
> all together, or something in between?

I rewrote it like:
wb_in  = None
wb_out = None
try:
wb_out = Workbook()
for filepath in filepathArr:
current_row = []
wb_in   = load_workbook(filepath)
for cell in wb_in.active[src_row]:
current_row.append(cell.value)
wb_out.active.append(current_row)
wb_in.close()
wb_out.save(report_start + datetime.now().strftime('%Y-%m-%d') + 
report_end)
wb_out.close()
messagebox.showinfo(info_str, created_report)
except Exception as err:
if wb_in:
wb_in.close()
if wb_out:
wb_close
messagebox.showerror(error_str,
 error_generate + '\n\n\n\n' + str(err))

Is it necessary to close the workbooks to circumvent a resource leak?
Is it a problem when a workbook is closed two times? If so I need to
make sure that this is not possible.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: What type of error is it

2019-06-26 Thread Cecil Westerhof
Cecil Westerhof  writes:

> I am writing a GUI program with tkinter. One function I have is:
> def select_dir():
> try:
> directory = filedialog.askdirectory()
> if directory == '':
> messagebox.showinfo(info_str, canceled_report)
> return
> chdir(directory)
> filepathArr = sorted(glob(regex))
> if len(filepathArr) == 0:
> messagebox.showwarning(warning_str, nofiles_str)
> return
> generate_report(filepathArr)
> except:
>messagebox.showerror(error_str, error_select_str)
>raise
>
> I use the raise to see what the exception was. That works, because
> tkinter takes over again.
> This works for me when I run it from the command-line, but it has to
> become a stand-alone executable. Is there a way to find out what the
> cause of the exception was, so I can put it in the error message?

Found it. I just need to change the last three lines to:
except Exception as err:
   messagebox.showerror(error_str,
    error_select_str + '\n\n\n\n' + str(err))

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


What type of error is it

2019-06-26 Thread Cecil Westerhof
I am writing a GUI program with tkinter. One function I have is:
def select_dir():
try:
directory = filedialog.askdirectory()
if directory == '':
messagebox.showinfo(info_str, canceled_report)
return
chdir(directory)
filepathArr = sorted(glob(regex))
if len(filepathArr) == 0:
messagebox.showwarning(warning_str, nofiles_str)
return
generate_report(filepathArr)
except:
   messagebox.showerror(error_str, error_select_str)
   raise

I use the raise to see what the exception was. That works, because
tkinter takes over again.
This works for me when I run it from the command-line, but it has to
become a stand-alone executable. Is there a way to find out what the
cause of the exception was, so I can put it in the error message?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Make sure the window title is visible in tkinter

2019-06-26 Thread Cecil Westerhof
I need to write a desktop program. I choose to use tkinter. How can I
make sure the window title is visible? For example when I have the
following code:
from tkinter  import Button, filedialog, Label, messagebox, Tk


window = Tk()
window.title('A long window title')
Button (window, text = 'Short text').pack()
window.mainloop()

I see only a part of the 'A', but I would like to see the complete:
'A long window title'

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Creating a Windows executable on a Linux system

2019-06-26 Thread Cecil Westerhof
I need to write a Python desktop program. I create it on a Linux
system, but it has to run on a Windows system. When looking at how to
create an executable it seems that you need to be on a Windows system
to create a Windows executable. Is this true, or is it possible to
create a Windows executable on a Linux system?

Any pointers about best practice creating a standalone executable are
welcome.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Copying a row from a range of Excel files to another

2019-06-26 Thread Cecil Westerhof
I was asked to copy a certain line from about 300 Excel lines to a new
Excel file. That is not something I would like to do by hand and I
immediately thought: that should be possible with Python.

And it is. I was surprised how fast I could write that with openpyxl.
My first try was not very neat, but a proof of concept. Then by
looking better at the possibilities I could get much cleaner code. But
I am still not completely happy. At the moment I have the following
code:
wb_out = Workbook()
for filepath in filepathArr:
current_row = []
wb_in   = load_workbook(filepath)
for cell in wb_in.active[src_row]:
current_row.append(cell.value)
wb_out.active.append(current_row)
wb_in.close()
wb_out.save(report_start + datetime.now().strftime('%Y-%m-%d') + report_end)
wb_out.close()

I could not find a way to copy a row from one workbook to another.
That is why I put the row in current_row and do an append. Am I
overlooking something, or is that really the way to do this?


I am not used to writing GUI programs. (I have to learn tkinter also.)
What is the best way to handle potential errors? It could go wrong on
line 1, 4, 5, 7, 8, 9 and 10. Should I catch every exception alone, or
all together, or something in between?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Handling an connection error with Twython

2019-06-01 Thread Cecil Westerhof
"Peter J. Holzer"  writes:

> On 2019-05-25 13:46:40 +0200, Cecil Westerhof wrote:
>> Just changing the while loop to a for loop did not make sense to me,
>> but this does. I now have:
>> max_tries = 5
>> for current_try in range(1, max_tries):
>> try:
>> posted = twitter.update_status(status = message,
>>in_reply_to_status_id = 
>> message_id,
>>trim_user = True)
>> return posted['id']
>> except TwythonError as e:
>> if not 'Temporary failure in name resolution' in e.msg:
>> raise
>> timed_message('Failed on try: {0} of {1}'.format(current_try, 
>> max_tries))
>> if current_try == max_tries:
>  
>  This will never be true because the loop will exit
>  before current_try reaches max_tries.
>> print('Could not get a connection to the internet: exiting')
>> deinit(2)
> Also you don't seem to stop here (unless deinit raises
> an exception)
>
>> time.sleep(60)
>> raise RuntimeError('Should not get here')
>  ^
>   So if you can't get a status update you will reach this point.

Oops, you are completely right. :'-( The for should be:
for current_try in range(1, max_tries + 1):

A bit silly of me.


The function deinit does some deinitialisation and after that an exit
with the value it receives. (Default it uses 0.) So you never return
from this call. Should have made that clear.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Handling an connection error with Twython

2019-05-25 Thread Cecil Westerhof
MRAB  writes:

> On 2019-05-24 09:25, Cecil Westerhof wrote:
>> Dennis Lee Bieber  writes:
>>
>>> On Fri, 24 May 2019 07:49:23 +0200, Cecil Westerhof 
>>> declaimed the following:
>>>
>>>>
>>>>I did not do that consciously, because I have to try until it is
>>>>successful an I return, or I reached the max tries and re-raise the
>>>>exception. With a for loop I could exit the loop and cannot re-raise
>>>>the exception.
>>>
>>> Your /success/ branch exits the loop by executing a "return" statement.
>>>
>>> Your /fail/ branch exits the loop by "raise" on the third failure.
>>>
>>> A "for" loop would have the same behavior; you just replace the manual
>>> initialization and increment of the loop counter.
>>>
>>> for tries in range(max_try):
>>> try:
>>> do something
>>> return successful
>>> except stuff:
>>> if tries+1 == max_try:  #since range is 0..max_try-1
>>> raise
>>>
>>> You never "fall off the end" of the loop.
>>
>> That is true, but by using a 'while True:' loop it is clear you never
>> fall off the end of the loop. I find this much clearer. And when there
>> is a bug you get into an endless loop instead of fall of the end.
>> Which in my opinion is easier to spot and mend. And endless loop is
>> noticed the moment it goes wrong. Falling of the end could go without
>> an error and will be spotted much later.
>>
> You could print a message or raise an exception after the 'for' loop so
> that if it ever falls off the end of the loop you'll get a nice message
> instead of it just looping forever! :-)
>

Just changing the while loop to a for loop did not make sense to me,
but this does. I now have:
max_tries = 5
for current_try in range(1, max_tries):
try:
posted = twitter.update_status(status = message,
   in_reply_to_status_id = message_id,
   trim_user = True)
return posted['id']
except TwythonError as e:
if not 'Temporary failure in name resolution' in e.msg:
raise
timed_message('Failed on try: {0} of {1}'.format(current_try, 
max_tries))
if current_try == max_tries:
print('Could not get a connection to the internet: exiting')
deinit(2)
time.sleep(60)
raise RuntimeError('Should not get here')

When I do not get an internet connection, I do not do a re-raise
anymore, but just give a message.

The proc deinit does a sys.exit after some cleanup.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Handling an connection error with Twython

2019-05-24 Thread Cecil Westerhof
Dennis Lee Bieber  writes:

> On Fri, 24 May 2019 07:49:23 +0200, Cecil Westerhof 
> declaimed the following:
>
>>
>>I did not do that consciously, because I have to try until it is
>>successful an I return, or I reached the max tries and re-raise the
>>exception. With a for loop I could exit the loop and cannot re-raise
>>the exception.
>
>   Your /success/ branch exits the loop by executing a "return" statement.
>
>   Your /fail/ branch exits the loop by "raise" on the third failure.
>
>   A "for" loop would have the same behavior; you just replace the manual
> initialization and increment of the loop counter.
>
>   for tries in range(max_try):
>   try:
>   do something
>   return successful
>   except stuff:
>   if tries+1 == max_try:  #since range is 0..max_try-1
>   raise
>
> You never "fall off the end" of the loop.

That is true, but by using a 'while True:' loop it is clear you never
fall off the end of the loop. I find this much clearer. And when there
is a bug you get into an endless loop instead of fall of the end.
Which in my opinion is easier to spot and mend. And endless loop is
noticed the moment it goes wrong. Falling of the end could go without
an error and will be spotted much later.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Handling an connection error with Twython

2019-05-24 Thread Cecil Westerhof
MRAB  writes:

> On 2019-05-23 22:55, Cecil Westerhof wrote:
>> Cecil Westerhof  writes:
>>
>>> I am using Twython to post updates on Twitter. Lately there is now and
>>> then a problem with my internet connection. I am using:
>>> posted = twitter.update_status(status = message,
>>>in_reply_to_status_id = message_id,
>>>trim_user = True)
>>>
>>> What would be the best way to catch a connection error and try it (for
>>> example) again maximum three times with a delay of one minute?
>>
>> At the moment I solved it with the following:
>>  max_tries   = 3
>>  current_try = 1
>>  while True:
>>  try:
>>  posted = twitter.update_status(status = message,
>> in_reply_to_status_id = 
>> message_id,
>> trim_user = True)
>>  return posted['id']
>>  except TwythonError as e:
>>  print('Failed on try: {0}'.format(current_try))
>>  if not 'Temporary failure in name resolution' in e.msg:
>>  raise
>>  if current_try == max_tries:
>>  raise
>>  current_try += 1
>>  time.sleep(60)
>>
>> Is this a good way to do it, or can it be improved on?
>>
>> When it goes OK I just return from the function.
>> If it goes wrong for something else as failure in the name resolution
>> I re-raise the exception.
>> When the maximum tries are done I re-raise the exception.
>> Otherwise I wait a minute to try it again.
>>
> You have a 'while' loop with a counter; you can replace that with a
> 'for' loop.

I did not do that consciously, because I have to try until it is
successful an I return, or I reached the max tries and re-raise the
exception. With a for loop I could exit the loop and cannot re-raise
the exception.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Handling an connection error with Twython

2019-05-23 Thread Cecil Westerhof
Cecil Westerhof  writes:

> I am using Twython to post updates on Twitter. Lately there is now and
> then a problem with my internet connection. I am using:
> posted = twitter.update_status(status = message,
>in_reply_to_status_id = message_id,
>trim_user = True)
>
> What would be the best way to catch a connection error and try it (for
> example) again maximum three times with a delay of one minute?

At the moment I solved it with the following:
max_tries   = 3
current_try = 1
while True:
try:
posted = twitter.update_status(status = message,
   in_reply_to_status_id = message_id,
   trim_user = True)
return posted['id']
except TwythonError as e:
print('Failed on try: {0}'.format(current_try))
if not 'Temporary failure in name resolution' in e.msg:
raise
if current_try == max_tries:
raise
current_try += 1
time.sleep(60)

Is this a good way to do it, or can it be improved on?

When it goes OK I just return from the function.
If it goes wrong for something else as failure in the name resolution
I re-raise the exception.
When the maximum tries are done I re-raise the exception.
Otherwise I wait a minute to try it again.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Handling an connection error with Twython

2019-05-23 Thread Cecil Westerhof
I am using Twython to post updates on Twitter. Lately there is now and
then a problem with my internet connection. I am using:
posted = twitter.update_status(status = message,
   in_reply_to_status_id = message_id,
   trim_user = True)

What would be the best way to catch a connection error and try it (for
example) again maximum three times with a delay of one minute?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Twython has a problem with latest urllib3

2018-10-19 Thread Cecil Westerhof
Cecil Westerhof  writes:

> I use Twython to post on Twitter. Yesterday I upgraded urllib3 from
> 1.23 to 1.24. Since then when I do:
> from twython import Twython
>
> I get:
> /usr/local/lib/python3.5/dist-packages/requests/__init__.py:91: 
> RequestsDependencyWarning: urllib3 (1.24) or chardet (3.0.4) doesn't match a 
> supported version!
>   RequestsDependencyWarning)
>
> Should I rollback urllib3, or hope that Twython is updated soon?
>
> It looks like that the functionality is not broken.

It was not Twython, but requests which is used by Twython. There is a
newer version of requests now and the problem is solved.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Twython has a problem with latest urllib3

2018-10-18 Thread Cecil Westerhof
I use Twython to post on Twitter. Yesterday I upgraded urllib3 from
1.23 to 1.24. Since then when I do:
from twython import Twython

I get:
/usr/local/lib/python3.5/dist-packages/requests/__init__.py:91: 
RequestsDependencyWarning: urllib3 (1.24) or chardet (3.0.4) doesn't match a 
supported version!
  RequestsDependencyWarning)

Should I rollback urllib3, or hope that Twython is updated soon?

It looks like that the functionality is not broken.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


ipython and prompt-toolkit

2018-09-27 Thread Cecil Westerhof
For a long time I cannot update prompt-toolkit, because ipython
requires a version lower as 2. That is why I still use 1.0.15 instead
of 2.0.4. Any chance that ipython will be updated concerning this
dependency?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Getting installed version

2018-07-20 Thread Cecil Westerhof
I can get the installed version of a package with:
pip2 show cryptography | awk '/^Version: / { print $2 }'

But I was wondering if there is a better way.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


How to get the versions of dependecies

2018-06-16 Thread Cecil Westerhof
If I update prompt-toolkit, I get:
ipython 6.4.0 has requirement prompt-toolkit<2.0.0,>=1.0.15, but you'll 
have prompt-toolkit 2.0.3 which is incompatible.

So I should not. At least not at the moment. But how do I get to know
which versions of a package are needed?

When Using:
pip3 -vvv show ipython

I just get:
Name: ipython
Version: 6.4.0
Summary: IPython: Productive Interactive Computing
Home-page: https://ipython.org
Author: The IPython Development Team
Author-email: ipython-...@python.org
License: BSD
Location: /usr/local/lib/python3.5/dist-packages
Requires: traitlets, decorator, pickleshare, backcall, prompt-toolkit, 
pexpect, jedi, simplegeneric, setuptools, pygments
Required-by: 
Metadata-Version: 2.0
Installer: pip
Classifiers:
  Framework :: IPython
  Intended Audience :: Developers
  Intended Audience :: Science/Research
  License :: OSI Approved :: BSD License
  Programming Language :: Python
  Programming Language :: Python :: 3
  Programming Language :: Python :: 3 :: Only
  Topic :: System :: Shells
Entry-points:
  [console_scripts]
  iptest = IPython.testing.iptestcontroller:main
  iptest3 = IPython.testing.iptestcontroller:main
  ipython = IPython:start_ipython
  ipython3 = IPython:start_ipython
  [pygments.lexers]
  ipython = IPython.lib.lexers:IPythonLexer
  ipython3 = IPython.lib.lexers:IPython3Lexer
  ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


urllib3 1.23 breaks API

2018-06-05 Thread Cecil Westerhof
I had installed urllib3 1.22 for Python3. I upgraded it to 1.23. This
broke the requirements for requests 2.18.4:
requests 2.18.4 has requirement urllib3<1.23,>=1.21.1, but you'll have 
urllib3 1.23 which is incompatible

I downgraded to 1.22, but this should not happen I think.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: ipython does not work with latest version of prompt-toolkit

2018-06-03 Thread Cecil Westerhof
Chris Warrick  writes:

> On Sun, 3 Jun 2018 at 10:32, Cecil Westerhof  wrote:
>>
>> When executing:
>> pip3 list --no-cache-dir --outdated
>>
>> I got:
>> prompt-toolkit 1.0.152.0.1wheel
>> PyGObject  3.28.23.28.3   sdist
>> youtube-dl 2018.5.30 2018.6.2 wheel
>>
>> So I executed:
>> pip3 install --upgrade prompt-toolkit PyGObject youtube-dl
>>
>> This gave:
>> Successfully installed PyGObject-3.28.3 prompt-toolkit-2.0.1 
>> youtube-dl-2018.6.2
>> ipython 6.4.0 has requirement prompt-toolkit<2.0.0,>=1.0.15, but you'll 
>> have prompt-toolkit 2.0.1 which is incompatible.
>>
>> And when I now execute ipython3, I get:
>> Traceback (most recent call last):
>>   File "/usr/local/bin/ipython3", line 7, in 
>> from IPython import start_ipython
>>   File "/usr/local/lib/python3.5/dist-packages/IPython/__init__.py", 
>> line 55, in 
>> from .terminal.embed import embed
>>   File 
>> "/usr/local/lib/python3.5/dist-packages/IPython/terminal/embed.py", line 16, 
>> in 
>> from IPython.terminal.interactiveshell import 
>> TerminalInteractiveShell
>>   File 
>> "/usr/local/lib/python3.5/dist-packages/IPython/terminal/interactiveshell.py",
>>  line 22, in 
>> from prompt_toolkit.shortcuts import create_prompt_application, 
>> create_eventloop, create_prompt_layout, create_output
>> ImportError: cannot import name 'create_prompt_application'
>>
>> When I now execute:
>> pip3 list --no-cache-dir --outdated
>>
>> I do not get output. So pip3 thinks everything is OK.
>>
>> How do I fix this? Or is the expected that ipython3 will be updated
>> shortly?
>
> Start by reading the warning from pip:
>
>> ipython 6.4.0 has requirement prompt-toolkit<2.0.0,>=1.0.15, but
>> you'll have prompt-toolkit 2.0.1 which is incompatible.
>
> To fix this, downgrade prompt-toolkit. `pip list --outdated` (not)
> having output isn’t a “good” or “bad” thing. prompt-toolkit v2 has
> changed its API from v1, and ipython doesn’t support the new one yet.

I did not find a command to get all the existing versions. I solved it
with uninstalling and then installing with:
pip3 install 'prompt-toolkit>=1.0.15,<2.0.0'

Is there a way to find the versions? It would be handy to install the
1.0.16 version if it comes out.


> Don’t randomly upgrade pip packages without knowing what the upgrade
> entails, especially if the version changed from 1.x to 2.x (x.y →
> x+1.y) — that usually means an API change and possible
> incompatibilities in dependent packages. Upgrading a tool like
> youtube-dl should be fine, and so should be a x.y.z → x.y.z+1 upgrade,
> but it’s still best to know what you’re doing.

Always checking would be a lot of work: I get several times a week
several packages to update. If I would check them all I need a few
hours more a week. I am used to systems that do not update when there
is a conflict. But sadly pip does not work that way. :'-(

But I could do the 'automatic' update only when x does not change. Or
for specific packages like youtube-dl.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


ipython does not work with latest version of prompt-toolkit

2018-06-03 Thread Cecil Westerhof
When executing:
pip3 list --no-cache-dir --outdated

I got:
prompt-toolkit 1.0.152.0.1wheel
PyGObject  3.28.23.28.3   sdist
youtube-dl 2018.5.30 2018.6.2 wheel

So I executed:
pip3 install --upgrade prompt-toolkit PyGObject youtube-dl

This gave:
Successfully installed PyGObject-3.28.3 prompt-toolkit-2.0.1 
youtube-dl-2018.6.2
ipython 6.4.0 has requirement prompt-toolkit<2.0.0,>=1.0.15, but you'll 
have prompt-toolkit 2.0.1 which is incompatible.

And when I now execute ipython3, I get:
Traceback (most recent call last):
  File "/usr/local/bin/ipython3", line 7, in 
from IPython import start_ipython
  File "/usr/local/lib/python3.5/dist-packages/IPython/__init__.py", line 
55, in 
from .terminal.embed import embed
  File "/usr/local/lib/python3.5/dist-packages/IPython/terminal/embed.py", 
line 16, in 
from IPython.terminal.interactiveshell import TerminalInteractiveShell
  File 
"/usr/local/lib/python3.5/dist-packages/IPython/terminal/interactiveshell.py", 
line 22, in 
from prompt_toolkit.shortcuts import create_prompt_application, 
create_eventloop, create_prompt_layout, create_output
ImportError: cannot import name 'create_prompt_application'

When I now execute:
pip3 list --no-cache-dir --outdated

I do not get output. So pip3 thinks everything is OK.

How do I fix this? Or is the expected that ipython3 will be updated
shortly?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: After update to pip 10 I get: Cache entry deserialization failed, entry ignored

2018-04-26 Thread Cecil Westerhof
tart...@gmail.com writes:

> On Wednesday, April 18, 2018 at 1:59:14 AM UTC-5, Cecil Westerhof wrote:
>> After I updated pip2/3 to 10 from 9 I sometimes get:
>> Cache entry deserialization failed, entry ignored
>> 
>> For example when I execute:
>> pip3 list --outdated
>> 
>> But not always.
>> 
>> What could be happening here? And how would I solve this?
>> 
>> -- 
>> Cecil Westerhof
>> Senior Software Engineer
>> LinkedIn: http://www.linkedin.com/in/cecilwesterhof
>
> It sounds like there's a bug in pip10 that makes the cache entries use a 
> different format for Python2 versus Python3.
> https://github.com/pypa/pip/issues/5250

I have seen that, but that did not work in my case.


> So either:
>
> * erase your cache directory. On *nix it's ~/.cache/pip.

That would make the usage of cache superfluous and I am wondering if
that is really the issue. See reply below.


> or
>
> * run pip with --no-cache-dir

Tried this, but it did not work.


> or
>
> * run pip with --cache-dir=X to set a different cache dir for Python2 vs 
> Python3.
>
> or
>
> * await a pip10 bugfix?

For the moment I do in my (tcl) script:
while {[catch ${command} errorStr opts]} {
incr errors
if {${debug}} {
puts 
puts ${opts}
puts 
}
if {${errors} >= ${maxTries}} {
error "Could not get ${pip} information with ${errors} tries"
}
}

There is not always a problem and if there is a problem it is never
more as once. (Till now.)
I use command because I do it for pip2 and pip3.
It is filled with:
# First 2 lines are a header
set command  {set outdated  \
  [lrange       \
   [split [exec ${pip} list --outdated] \n] \
   2 end]}
And pip is pip2 or pip3.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


After update to pip 10 I get: Cache entry deserialization failed, entry ignored

2018-04-18 Thread Cecil Westerhof
After I updated pip2/3 to 10 from 9 I sometimes get:
Cache entry deserialization failed, entry ignored

For example when I execute:
pip3 list --outdated

But not always.

What could be happening here? And how would I solve this?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Strange problem with pip2

2018-03-01 Thread Cecil Westerhof
There are three pip2 packages that should be updated:
apsw (3.13.0.post1) - Latest: 3.9.2.post1 [sdist]
mysql-utilities (1.6.4) - Latest: 1.4.3 [sdist]
pygobject (3.22.0) - Latest: 3.27.4 [sdist]

But the strange thing is that the installed version is newer as the
new version. And when I try:
pip2 install --upgrade apsw

I get:
Requirement already up-to-date: apsw in /usr/lib/python2.7/dist-packages

But with pygobject the problem is even stranger, when I try to update
this, it end with:
command "/usr/bin/python -u -c "import setuptools, 
tokenize;__file__='/tmp/pip-build-vY4LXH/pycairo/setup.py';f=getattr(tokenize, 
'open', open)(__file__);code=f.read().replace('\r\n', 
'\n');f.close();exec(compile(code, __file__, 'exec'))" install --record 
/tmp/pip-40OPWv-record/install-record.txt --single-version-externally-managed 
--compile" failed with error code 1 in /tmp/pip-build-vY4LXH/pycairo/


What could be happening here? And how do I solve this?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Replying on a tweet with Twython

2018-02-17 Thread Cecil Westerhof
Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> writes:

> On Sat, 17 Feb 2018 12:53:08 +0100, Cecil Westerhof wrote:
>
>> Cecil Westerhof <ce...@decebal.nl> writes:
>> 
>>> I just found Twython. I managed to post a tweet with:
>>> from twython import Twython
>>> twitter = Twython(APP_KEY, APP_SECRET,
>>>   OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
>>> posted = twitter.update_status(status = quote)
>>>
>>> But I want to send a reply on this tweet. I tried:
>>> posted = twitter.update_status(status = follow_up, in_reply_id
>>> = posted['id_str'])
>>>
>>> But that does not work. How could I make it work?
>
> Define "does not work". What happens when you try?

It is posted as a standalone tweet instead of as a reply on the first
tweet.


>> I need to use the following:
>> posted = twitter.update_status(status = follow_up,
>> in_reply_to_status_id = posted['id'])
>
> Okay. What happens when you try?

Then the tweet is posted as a reply on the the first tweet.

(So problem solved.)

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Replying on a tweet with Twython

2018-02-17 Thread Cecil Westerhof
Cecil Westerhof <ce...@decebal.nl> writes:

> I just found Twython. I managed to post a tweet with:
> from twython import Twython
> twitter = Twython(APP_KEY, APP_SECRET,
>   OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
> posted = twitter.update_status(status = quote)
>
> But I want to send a reply on this tweet. I tried:
> posted = twitter.update_status(status = follow_up, in_reply_id = 
> posted['id_str'])
>
> But that does not work. How could I make it work?

I need to use the following:
posted = twitter.update_status(status = follow_up, in_reply_to_status_id = 
posted['id'])

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Replying on a tweet with Twython

2018-02-17 Thread Cecil Westerhof
I just found Twython. I managed to post a tweet with:
from twython import Twython
twitter = Twython(APP_KEY, APP_SECRET,
  OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
posted = twitter.update_status(status = quote)

But I want to send a reply on this tweet. I tried:
posted = twitter.update_status(status = follow_up, in_reply_id = 
posted['id_str'])

But that does not work. How could I make it work?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: From recovery.js to recoveryjsonlz4

2018-02-06 Thread Cecil Westerhof
breamore...@gmail.com writes:

> On Monday, February 5, 2018 at 1:28:16 PM UTC, Cecil Westerhof wrote:
>> I have a script to get the number of windows and tabs that firefox
>> uses. It always used a file recovery.js, but it changed to
>> recovery.jsonlz4.
>> 
>> Looking at the extension I would think it is an lz4 compressed file.
>> But when I use:
>> import lz4
>> 
>> I see that it is deprecated. How should I work with this file?
>> 
>
> I can't see anything here
> http://python-lz4.readthedocs.io/en/stable/lz4.html to indicate that the
> package is deprecated, although the lz4version function has been since
> version 0.14. Further the latest 0.21.6 was released just yesterday,
> 04/02/2018, so I'm guessing that you've just misread something.

Well, when using 'import lz4' and giving tab in ipython, you get:
deprecated
library_version_number
library_version_string
lz4version
VERSION
version

Looking at:
http://python-lz4.readthedocs.io/en/stable/lz4.frame.html

I tried to replace:
loads(open(recover, 'rb').read().decode('utf-8'))

With:
import lz4.frame
.
.
.
lz4.frame.open(recover, 'rb').read().decode('utf-8')

But this gives:
--
RuntimeError  Traceback (most recent call last)
 in ()
> 1 dummy = lz4.frame.open(recover, 'rb').read().decode('utf-8')

/usr/local/lib/python3.5/dist-packages/lz4/frame/__init__.py in read(self, 
size)
507 """
508 self._check_can_read()
--> 509 return self._buffer.read(size)
510 
511 def read1(self, size=-1):

/usr/lib/python3.5/_compression.py in read(self, size)
101 else:
102 rawblock = b""
--> 103 data = self._decompressor.decompress(rawblock, size)
104 if data:
105 break

/usr/local/lib/python3.5/dist-packages/lz4/frame/__init__.py in 
decompress(self, data, max_length)
295 data,
296 max_length=max_length,
--> 297 return_bytearray=self._return_bytearray,
298 )
299 

RuntimeError: LZ4F_decompress failed with code: ERROR_frameType_unknown

What works is:
dummy = lz4.frame.open(recover, 'rb')

And this gives a:


But when I then do:
input = dummy.read()

I get (as above):
---
RuntimeError  Traceback (most recent call last)
 in ()
> 1 input = dummy.read()

/usr/local/lib/python3.5/dist-packages/lz4/frame/__init__.py in read(self, 
size)
507 """
508 self._check_can_read()
--> 509 return self._buffer.read(size)
510 
511 def read1(self, size=-1):

/usr/lib/python3.5/_compression.py in read(self, size)
101 else:
102 rawblock = b""
--> 103 data = self._decompressor.decompress(rawblock, size)
104 if data:
105 break

/usr/local/lib/python3.5/dist-packages/lz4/frame/__init__.py in 
decompress(self, data, max_length)
295 data,
296 max_length=max_length,
--> 297 return_bytearray=self._return_bytearray,
298 )
299 

RuntimeError: LZ4F_decompress failed with code: ERROR_frameType_unknown

So how do I circumvent this error to read the file?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


From recovery.js to recoveryjsonlz4

2018-02-05 Thread Cecil Westerhof
I have a script to get the number of windows and tabs that firefox
uses. It always used a file recovery.js, but it changed to
recovery.jsonlz4.

Looking at the extension I would think it is an lz4 compressed file.
But when I use:
import lz4

I see that it is deprecated. How should I work with this file?

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


How to use a regexp here

2017-12-08 Thread Cecil Westerhof
I have a script that was running perfectly for some time. It uses:
array = [elem for elem in output if 'CPU_TEMP' in elem]

But because output has changed, I have to check for CPU_TEMP at the beginning
of the line. What would be the best way to implement this?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

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


Re: How to use a regexp here

2017-12-08 Thread Cecil Westerhof
Rick Johnson <rantingrickjohn...@gmail.com> writes:

>> There is now also a line that starts with: PCH_CPU_TEMP:
>> And I do not want that one.
>
> Yes. But be aware, that while the `str.startswith(target)`
> method is indeed more efficient than a more generalized
> "inclusion test", if the target is not _always_ at the
> beginning of the string, then your code is going to skip
> right over valid match like a round stone skipping across
> the surface of a glass-smooth lake. But if you are sure the
> target will always be at the beginning of the string, then
> it is the best choice.

Yes, I am sure it is always at the beginning of the line. (It is output from
the Linux sensors command.)

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

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


Re: How to use a regexp here

2017-12-08 Thread Cecil Westerhof
Neil Cerutti <ne...@norwich.edu> writes:

> On 2017-12-04, Cecil Westerhof <ce...@decebal.nl> wrote:
>> Joel Goldstick <joel.goldst...@gmail.com> writes:
>>
>>> On Mon, Dec 4, 2017 at 5:21 AM, Ned Batchelder <n...@nedbatchelder.com>
>>> wrote:
>>>
>>>> On 12/4/17 4:36 AM, Cecil Westerhof wrote:
>>>>
>>>>> I have a script that was running perfectly for some time. It uses:
>>>>>  array = [elem for elem in output if 'CPU_TEMP' in elem]
>>>>>
>>>>> But because output has changed, I have to check for CPU_TEMP at the
>>>>> beginning of the line. What would be the best way to implement this?
>>>>>
>>>>>
>>>> No need for a regex just yet:
>>>>
>>>> array = [elem for elem in output if elem.startswith('CPU_TEMP')]
>>>>
>>>> (btw, note that the result of this expression is a list, not an array, for
>>>> future Googling.)
>>>>
>>>> --Ned.
>>>> --
>>>> https://mail.python.org/mailman/listinfo/python-list
>>>>
>>>
>>> I like Ned's clear answer, but I'm wondering why the original code would
>>> fail because the substring is at the start of the line, since 'in' would
>>> still be true no matter where the desired string is placed.  It would be
>>> useful to see some sample data of the old data, and the new data
>>
>> There is now also a line that starts with:
>> PCH_CPU_TEMP:
>>
>> And I do not want that one.
>
> You'll probably want to include the ':' in the startswith check,
> in case someday they also add CPU_TEMP_SOMETHING:.

I already did. And to be really sure also included a space after it.

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

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


Re: How to use a regexp here

2017-12-08 Thread Cecil Westerhof
Joel Goldstick <joel.goldst...@gmail.com> writes:

> On Mon, Dec 4, 2017 at 5:21 AM, Ned Batchelder <n...@nedbatchelder.com>
> wrote:
>
>> On 12/4/17 4:36 AM, Cecil Westerhof wrote:
>>
>>> I have a script that was running perfectly for some time. It uses:
>>>  array = [elem for elem in output if 'CPU_TEMP' in elem]
>>>
>>> But because output has changed, I have to check for CPU_TEMP at the
>>> beginning of the line. What would be the best way to implement this?
>>>
>>>
>> No need for a regex just yet:
>>
>> array = [elem for elem in output if elem.startswith('CPU_TEMP')]
>>
>> (btw, note that the result of this expression is a list, not an array, for
>> future Googling.)
>>
>> --Ned.
>> --
>> https://mail.python.org/mailman/listinfo/python-list
>>
>
> I like Ned's clear answer, but I'm wondering why the original code would
> fail because the substring is at the start of the line, since 'in' would
> still be true no matter where the desired string is placed.  It would be
> useful to see some sample data of the old data, and the new data

There is now also a line that starts with:
PCH_CPU_TEMP:

And I do not want that one.

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

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


Re: How to use a regexp here

2017-12-08 Thread Cecil Westerhof
Ned Batchelder <n...@nedbatchelder.com> writes:

> On 12/4/17 4:36 AM, Cecil Westerhof wrote:
>> I have a script that was running perfectly for some time. It uses:
>>  array = [elem for elem in output if 'CPU_TEMP' in elem]
>>
>> But because output has changed, I have to check for CPU_TEMP at the
>> beginning of the line. What would be the best way to implement this?
>>
>
> No need for a regex just yet:
>
> â â â  array = [elem for elem in output if elem.startswith('CPU_TEMP')]

Yes, that is it. I should have known that. :'-(

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

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


Re: How to use a regexp here

2017-12-04 Thread Cecil Westerhof
Neil Cerutti <ne...@norwich.edu> writes:

> On 2017-12-04, Cecil Westerhof <ce...@decebal.nl> wrote:
>> Joel Goldstick <joel.goldst...@gmail.com> writes:
>>
>>> On Mon, Dec 4, 2017 at 5:21 AM, Ned Batchelder <n...@nedbatchelder.com>
>>> wrote:
>>>
>>>> On 12/4/17 4:36 AM, Cecil Westerhof wrote:
>>>>
>>>>> I have a script that was running perfectly for some time. It uses:
>>>>>  array = [elem for elem in output if 'CPU_TEMP' in elem]
>>>>>
>>>>> But because output has changed, I have to check for CPU_TEMP at the
>>>>> beginning of the line. What would be the best way to implement this?
>>>>>
>>>>>
>>>> No need for a regex just yet:
>>>>
>>>> array = [elem for elem in output if elem.startswith('CPU_TEMP')]
>>>>
>>>> (btw, note that the result of this expression is a list, not an array, for
>>>> future Googling.)
>>>>
>>>> --Ned.
>>>> --
>>>> https://mail.python.org/mailman/listinfo/python-list
>>>>
>>>
>>> I like Ned's clear answer, but I'm wondering why the original code would
>>> fail because the substring is at the start of the line, since 'in' would
>>> still be true no matter where the desired string is placed.  It would be
>>> useful to see some sample data of the old data, and the new data
>>
>> There is now also a line that starts with:
>> PCH_CPU_TEMP:
>>
>> And I do not want that one.
>
> You'll probably want to include the ':' in the startswith check,
> in case someday they also add CPU_TEMP_SOMETHING:.

I already did. And to be really sure also included a space after it.

-- 
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof
-- 
https://mail.python.org/mailman/listinfo/python-list


  1   2   3   4   5   >