Re: Tkinter and cv2: "not responding" popup when imshow launched from tk app

2023-03-15 Thread aapost

On 3/15/23 07:37, John O'Hagan wrote:

On Tue, 2023-03-14 at 16:22 -0400, aapost wrote:

On 3/14/23 06:54, John O'Hagan wrote:




Doing a quick read, tkinter is not threadsafe, so diving in to a 
threading solution is probably not the best approach.


But just to throw out another possible solution to see if you can find a 
"good enough" work around that fits your desired behavior.


You could spawn the imshow as it's own program:

file2: sp.py

import sys
import cv2
import tkinter as tk
def show(img, root):
   cv2.namedWindow(str(root), cv2.WND_PROP_FULLSCREEN)
   cv2.setWindowProperty(str(root), cv2.WND_PROP_FULLSCREEN, 
cv2.WINDOW_FULLSCREEN)

   cv2.imshow(str(root), cv2.imread(img))
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   exit()
root=tk.Tk()
show(sys.argv[1], root)
tk.mainloop()


file1:main.py

import cv2
import tkinter as tk
import subprocess
images=['c.jpg', 'b.jpg', 'c.jpg']
control = {
"counter" : 0,
"pid": None
}
def show(control):
   if control["pid"]:
 control["pid"].kill()
   control["pid"] = subprocess.Popen(["python", "sp.py", 
images[control["counter"] % len(images)]])

   control["counter"] += 1
root=tk.Tk()
root.wm_attributes("-topmost", 1)
tk.Button(root, text=' Show ', command=lambda: show(control)).pack()
tk.mainloop()


refactor/design as needed, you track the pid, kill the existing on each 
subsequent show press.


caveats would be that since it is an entirely separate program, if you 
close the main window, the other window will still linger until it is 
also closed. You could try to catch the close to run a .kill() on the 
subprocess if you want right before the exit, etc.


But this gives control back to the main GUI since they are now 
independent of each other and not within the same thread.


If they need to talk to each other in some way more than that, I am sure 
deeper design solutions could be thought up.

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


Re: Running asyncio.run() more than once

2023-03-15 Thread Clint Olsen
On Monday, March 13, 2023 at 11:32:23 PM UTC-7, Clint Olsen wrote:
> We have an application that involves submitting hundreds to thousands of jobs 
> to a shared computing resource, and we're using asyncio to do so because it 
> is far less overhead than threading or multiprocessing for the bookkeeping 
> required to keep track of all these jobs. It makes extensive use of 
> asyncio.create_subprocess_exec(). This was developed mostly in Python 3.9.7. 

Good news! I did end up finding the source of the problem. I kept looking for 
the use of global data as a potential source of bugs and didn't really find 
anything there. I did fix some potential signal handler problems. However I had 
this particular piece of code that I needed to follow my processes.

watcher = asyncio.FastChildWatcher()
watcher.attach_loop(asyncio.get_event_loop())
asyncio.set_child_watcher(watcher)

Since async reuses the same event loop on successive calls, doing this again is 
bad. I just needed to ensure I only set this once.

Thanks,

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


Re: Implementing a plug-in mechanism

2023-03-15 Thread Thomas Passin

On 3/15/2023 6:06 PM, Weatherby,Gerard wrote:

I do something similar to Thomas. (Also MIT licensed). I like objects. I like 
type hints.

Each plugin needs to have check and purpose functions and accepts either 
PluginSpec (by default) or AddonSpec if it defines addon = True


I omitted the checks because they specific to the use, so I thought they 
would just be a bit confusing.


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


Re: Implementing a plug-in mechanism

2023-03-15 Thread Weatherby,Gerard
I do something similar to Thomas. (Also MIT licensed). I like objects. I like 
type hints.

Each plugin needs to have check and purpose functions and accepts either 
PluginSpec (by default) or AddonSpec if it defines addon = True

This requires a single-level plugin directory with no extra files in it (unless 
they start with _, like __init__.py)


And I should use os.path.splitext but I forget what’s it called and find it 
easier just to split.

# noinspection PyUnresolvedReferences
@dataclass
class NamedModule:
"""Datacheck module and its name"""
mod: object
name: str

def __post_init__(self):
"""Validate attributes"""
assert hasattr(self.mod, 'check')
assert hasattr(self.mod, 'purpose')

def check(self, inspec: Union[PluginSpec, AddonSpec]) -> PluginResult:
return self.mod.check(inspec)

@property
def purpose(self) -> str:
return self.mod.purpose()

@property
def addon(self) -> bool:
"""Return true if this module uses AddonSpec"""
return getattr(self.mod, 'addon', False)


class Integrity:

   @property
def plugins(self) -> List[NamedModule]:
"""Get list of plugins by scanning plugin directory"""
modules = []
us = os.path.abspath(__file__)
plugin_dir = os.path.join(os.path.dirname(us), 'plugins')
de: os.DirEntry
for de in os.scandir(plugin_dir):
if not de.name.startswith('_'):
n = de.name.split('.')[0]
mod = importlib.import_module(f'.plugins.{n}', 'dataintegrity')
modules.append(NamedModule(mod, n))
return modules
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Implementing a plug-in mechanism

2023-03-15 Thread Thomas Passin

On 3/15/2023 2:45 PM, dn via Python-list wrote:

On 16/03/2023 01.47, Loris Bennett wrote:

I have written a program which, as part of the non-core functionality,
contains a module to generate email.  This is currently very specific
to my organisation, so the main program contains

   import myorg.mailer

This module is specific to my organisation in that it can ask an
internal server to generate individualised salutations for a given UID
which is known within the organisation.

I want to share the code with other institutions, so I would like to

   1. replace the organisation-specific mailer with a generic one
   2. allow an organisation-specific mailer to be used instead of the
  generic one, if so desired


This may call for the plug-in pattern, ie the user will choose whether 
to plug-in the specific, or the generic, module.


In Python, we would tend to use a Dependency Injection approach (one of 
Uncle Bob's SOLID principles).

[snip]

Here is (slightly modified) plugin code I'm using in one project.  You 
could use a naming convention to see if there is a plugin for a specific 
organizations, or each module could contain a UID variable which you 
could inspect to find the desired one.  This code is under the MIT 
License, so feel free to adapt it if you like.


def import_all_plugins(plugins_import_list, plugin_dir):
"""Import modules from the plugins directory and return a list of them.

If plugins_import_list is not empty or None, only import the ones
listed there. Otherwise import all ".py" files.

RETURNS
a list of successfully imported modules.
"""
modules = []

if not plugins_import_list:
plugins_import_list = []
for root, dirs, files in os.walk(plugin_dir):
if root == plugin_dir:
break
for f in files:
f, ext = os.path.splitext(f)
if ext == '.py':
plugins_import_list.append(f)

for f in plugins_import_list:
try:
mod = importlib.import_module(f'plugins.{f}')
modules.append(mod)
except ImportError as e:
print(f'{__name__}: {f} plugin: {e}')
continue
return modules


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


Re: Tkinter and cv2: "not responding" popup when imshow launched from tk app

2023-03-15 Thread aapost

On 3/15/23 07:37, John O'Hagan wrote:

On Tue, 2023-03-14 at 16:22 -0400, aapost wrote:

On 3/14/23 06:54, John O'Hagan wrote:

It works up to a point - I can cycle through the images by clicking
the
button - but if I mouse-click on the displayed image (e.g. to use
the
zooming and panning features of cv2), nothing happens, and a few
seconds later the image greys out and a popup appears saying
"'Unknown'
is not responding" and giving the option of waiting or forcing
close
(but sometimes these options are greyed out too). Clicking "wait",
if
available, closes the popup but it comes back a few seconds later.
If I
then click on the tkinter window titlebar, the popup changes
to "'Tk'
is not responding". Clicking on the button still works and after a
few
clicks the popup closes.


[...]


I think this particular popup is a Gnome thing, but AIUI most DEs
have
something similar to detect stuck apps. But the app is not stuck.

I suspect this is some kind of interaction between the call to
cv2.waitKey (which is necessary but I've never understood why!) and
the
tkinter event loop, but it's beyond my knowledge.

Any suggestions about causes or workarounds?

Thanks

--

John





I don't get any of the zoom/panning behavior with waitKey(1). But a
couple notes from the web:


https://docs.opencv.org/2.4/modules/highgui/doc/user_interface.html

Note

This function should be followed by waitKey function which displays
the
image for specified milliseconds. Otherwise, it won’t display the
image.
For example, waitKey(0) will display the window infinitely until any
keypress (it is suitable for image display). waitKey(25) will display
a
frame for 25 ms, after which display will be automatically closed.
(If
you put it in a loop to read videos, it will display the video
frame-by-frame)

https://pythonexamples.org/python-opencv-imshow/

cv2.waitKey(0) is important for holding the execution of the python
program at this statement, so that the image window stays visible. If
you do not provide this statement, cv2.imshow() executes in fraction
of
a second and the program closes all the windows it opened, which
makes
it almost impossible to see the image on the window.

if I change waitKey to 0, I get the ability to zoom/pan, but it
places
the tk window in a blocked state because it is waiting on cv2 to
return.
If I hit the ESC key, it releases the wait and gives control back to
the
tk window, allowing me to press show again to continue to the next
image.

I can try to change waitKey to a high ms like 1000 and have
zoom/pan
for that amount of time before it gives control back to tk (not a
sensical approach).

The fact that you can still see the image after tk takes back control
is
I believe just a matter of design, some examples show
cv2.destroyAllWindows() after waitKey(0) to clean that up, but of
course
if you are reusing the same window, that destroys the target.

You can resolve that if you move
cv2.namedWindow('W', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('W', cv2.WND_PROP_FULLSCREEN,
cv2.WINDOW_FULLSCREEN)

to inside the show, and destroy it after the wait, and make waitKey
0,
this allows creation/cleanup of that window per image

Hitting ESC when done zooming/panning on each image to get back to
tk.


Thanks for your reply.

I'm afraid in the real app it won't be practical to have no gui control
while viewing images.

But your suggestions have made me realise that my issue has nothing to
do with tkinter, it seems to be the way imshow is supposed to work.
This code gives the same behaviour described above:

cv2.imshow('W', array)
cv2.waitKey(100)
time.sleep(20)

I've seen the docs you mention that say the window will close if no
keypress happens within the waitKey time, but that doesn't seem to be
what happens as you say. After waitKey returns, the image remains and
everything works, but for some reason the desktop complains about an
unresponsive app.

You can use cv2 to display video with:

while 1:
  frame = camera.read() #pseudocode
  cv2.imshow('W', frame)
  cv2.waitKey(1)

(In fact this used to work without waitKey if you called
cv2.startWindowThread() after creating the window, but that stopped
working at some point.)

The fact that this works, presumably because the image is being
replaced often enough, suggested the following workaround to my
problem, using a call to after() to re-display the current image before
the desktop starts complaining:

images=[cv2.imread(i) for i in ('a.jpg', 'b.jpg', 'c.jpg')]

cv2.namedWindow('W', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('W', cv2.WND_PROP_FULLSCREEN,
cv2.WINDOW_FULLSCREEN)

counter=[0]

image = [None]

def show():
im = images[counter[0] % 3]
cv2.imshow('W', im)
cv2.waitKey(1)
image[:] = [im]
counter[0] += 1

root=Tk()
root.wm_attributes("-topmost", 1)
b=Button(root, text=' Show ', command=show)
b.pack()

def update():
if image[0] is not None:
   cv2.imshow('W', image[0])
   cv2.waitKey(1)
   root.after(1000, update)

update

Re: Implementing a plug-in mechanism

2023-03-15 Thread dn via Python-list

On 16/03/2023 01.47, Loris Bennett wrote:

I have written a program which, as part of the non-core functionality,
contains a module to generate email.  This is currently very specific
to my organisation, so the main program contains

   import myorg.mailer

This module is specific to my organisation in that it can ask an
internal server to generate individualised salutations for a given UID
which is known within the organisation.

I want to share the code with other institutions, so I would like to

   1. replace the organisation-specific mailer with a generic one
   2. allow an organisation-specific mailer to be used instead of the
  generic one, if so desired


This may call for the plug-in pattern, ie the user will choose whether 
to plug-in the specific, or the generic, module.


In Python, we would tend to use a Dependency Injection approach (one of 
Uncle Bob's SOLID principles).


There's a rather abstract description of the plugin pattern at 
https://martinfowler.com/eaaCatalog/plugin.html


OpenClassrooms has a more practical discussion at 
https://openclassrooms.com/en/courses/6397806-design-your-software-architecture-using-industry-standard-patterns/6896171-plug-in-architecture


There is a PyPi library called pluggy (not used it). I've used informal 
approaches using an ABC as a framework/reminder (see @George's response).


--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list


Re: Implementing a plug-in mechanism

2023-03-15 Thread Weatherby,Gerard
Yes, that works, and I’ve used that on a couple of projects.

Another alternative is defining an Abstract Base Class, 
https://docs.python.org/3/library/abc.html, and having an institution-specific 
implementation passed into your module.

From: Python-list  on 
behalf of Loris Bennett 
Date: Wednesday, March 15, 2023 at 1:03 PM
To: python-list@python.org 
Subject: Implementing a plug-in mechanism
*** Attention: This is an external email. Use caution responding, opening 
attachments or clicking on links. ***

Hi,

I have written a program which, as part of the non-core functionality,
contains a module to generate email.  This is currently very specific
to my organisation, so the main program contains

  import myorg.mailer

This module is specific to my organisation in that it can ask an
internal server to generate individualised salutations for a given UID
which is known within the organisation.

I want to share the code with other institutions, so I would like to

  1. replace the organisation-specific mailer with a generic one
  2. allow an organisation-specific mailer to be used instead of the
 generic one, if so desired

Is importlib the way to go here or is there another approach?

Cheers,

Loris

--
This signature is currently under constuction.
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!izCZs2X5PFeGpCF4TrtdDABzPqCFFT5i89Zsu-msRJAIpyWZYybdHDOFdxno9J3JvpNsRRQK9w72qgYj0MjlB2L-LsVXW1o$
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread Weatherby,Gerard
Moving the generator out:

import timeit

thedata = [i for i in range(1_000_000)]
def sum1():
s = 0
for i in thedata:
s += i
return s

def sum2():
return sum(thedata)

print('For Loop Sum:', timeit.timeit(sum1, number=100))
print( 'Built-in Sum:', timeit.timeit(sum2, number=100))

---
For Loop Sum: 6.984986504539847
Built-in Sum: 0.5175364706665277

From: Weatherby,Gerard 
Date: Wednesday, March 15, 2023 at 1:09 PM
To: python-list@python.org 
Subject: Re: Debugging reason for python running unreasonably slow when adding 
numbers
Sum is faster than iteration in the general case.

Lifting a test program from Stack Overflow 
https://stackoverflow.com/questions/24578896/python-built-in-sum-function-vs-for-loop-performance,


import timeit

def sum1():
s = 0
for i in range(100):
s += i
return s

def sum2():
return sum(range(100))

print('For Loop Sum:', timeit.timeit(sum1, number=100))
print( 'Built-in Sum:', timeit.timeit(sum2, number=100))

---

For Loop Sum: 7.726335353218019
Built-in Sum: 1.0398506000638008

---


From: Python-list  on 
behalf of David Raymond 
Date: Wednesday, March 15, 2023 at 11:46 AM
To: python-list@python.org 
Subject: RE: Debugging reason for python running unreasonably slow when adding 
numbers
*** Attention: This is an external email. Use caution responding, opening 
attachments or clicking on links. ***

> Then I'm very confused as to how things are being done, so I will shut
> up. There's not enough information here to give performance advice
> without actually being a subject-matter expert already.

Short version: In this specific case "weights" is a 5,147 element list of 
floats, and "input" is a 10 element list of integers which has the indexes of 
the 10 elements in weights that he wants to add up.

sum_ = 0
for key in input:
sum_ += weights[key]

vs

sum_ = sum(weights[key] for key in input)

vs... other ways
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ikhJJxqJnllDHh6JKaMX8g2K-Ceq6ZiRDJxX7AbS-1AiBIrdAmA2qjBtYZbxel2mktyno1s9iJGo_zAl5alBIWxoVXE$
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread Weatherby,Gerard
Sum is faster than iteration in the general case.

Lifting a test program from Stack Overflow 
https://stackoverflow.com/questions/24578896/python-built-in-sum-function-vs-for-loop-performance,

import timeit

def sum1():
s = 0
for i in range(100):
s += i
return s

def sum2():
return sum(range(100))

print('For Loop Sum:', timeit.timeit(sum1, number=100))
print( 'Built-in Sum:', timeit.timeit(sum2, number=100))

---

For Loop Sum: 7.726335353218019
Built-in Sum: 1.0398506000638008

---

From: Python-list  on 
behalf of David Raymond 
Date: Wednesday, March 15, 2023 at 11:46 AM
To: python-list@python.org 
Subject: RE: Debugging reason for python running unreasonably slow when adding 
numbers
*** Attention: This is an external email. Use caution responding, opening 
attachments or clicking on links. ***

> Then I'm very confused as to how things are being done, so I will shut
> up. There's not enough information here to give performance advice
> without actually being a subject-matter expert already.

Short version: In this specific case "weights" is a 5,147 element list of 
floats, and "input" is a 10 element list of integers which has the indexes of 
the 10 elements in weights that he wants to add up.

sum_ = 0
for key in input:
sum_ += weights[key]

vs

sum_ = sum(weights[key] for key in input)

vs... other ways
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!ikhJJxqJnllDHh6JKaMX8g2K-Ceq6ZiRDJxX7AbS-1AiBIrdAmA2qjBtYZbxel2mktyno1s9iJGo_zAl5alBIWxoVXE$
-- 
https://mail.python.org/mailman/listinfo/python-list


Implementing a plug-in mechanism

2023-03-15 Thread Loris Bennett
Hi,

I have written a program which, as part of the non-core functionality,
contains a module to generate email.  This is currently very specific
to my organisation, so the main program contains

  import myorg.mailer  

This module is specific to my organisation in that it can ask an
internal server to generate individualised salutations for a given UID
which is known within the organisation.

I want to share the code with other institutions, so I would like to 

  1. replace the organisation-specific mailer with a generic one
  2. allow an organisation-specific mailer to be used instead of the
 generic one, if so desired

Is importlib the way to go here or is there another approach?

Cheers,

Loris
 
-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Distributing program for Linux

2023-03-15 Thread Loris Bennett
Anssi Saari  writes:

> "Loris Bennett"  writes:
>
>> I am aware that an individual user could use (mini)conda to install a
>> more recent version of Python in his/her home directory, but I am
>> interested in how root would install such a program.
>
> Root would install the script and required Python version somewhere
> depending any site specific practices and then use things like pyenv,
> stow, environment modules or whatever to give the users access to it.

The program is not for normal users, but is a system program.  Many
admins who might install the program will be using environment modules,
so that, coupled with setting

  #!/usr/bin/env python3

for the scripts, looks like it might be a reasonable solution.

> Root might even package your script with the interpreter required into
> one binary. See Tools/freeze in the source distribution.

Well, anyone who has the sources can do that, if so inclined.
Personally, I already have enough versions of Python (currently 12
versions installed via EasyBuild plus the 2 from the OS itself) without
creating fat binaries which contain a copy of one of those version.

Cheers,

Loris

-- 
This signature is currently under constuction.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Distributing program for Linux

2023-03-15 Thread Loris Bennett
"Weatherby,Gerard"  writes:

> It’s really going to depend on the distribution and whether you have root 
> access.

I am interested in providing a package for people with root access for a
variety of distributions.

> If you have Ubuntu and root access, you can add the deadsnakes repo,
> https://launchpad.net/~deadsnakes, and install whatever Python you
> want.

I myself have this part covered via EasyBuild, https://easybuild.io/,
which will work on any distro.  How anybody else installs a given
version Python will be left as an exercise for them (potential users of
the software are however unlikely to be using Ubuntu).

> The default ‘python3’ remains but you can called a specific Python, (e.g. 
> python3.10).
>
> A typical shebang line would be:
>
> #!/usr/bin/env python3.10

I am currently using poetry to build the package and uses a 'scripts'
section in the pyproject.toml file to produce stubs to call the main
program.  These have the shebang

  #!/usr/bin/python3

So if I can get poetry to use '/usr/bin/env' instead, then I can
probably just rely on whatever mechanism other people use to switch
between Python versions to do the right thing.

Cheers,

Loris

> From: Python-list 
> on behalf of Loris Bennett 
> Date: Tuesday, March 14, 2023 at 12:27 PM
> To: python-list@python.org 
> Subject: Distributing program for Linux
> *** Attention: This is an external email. Use caution responding, opening 
> attachments or clicking on links. ***
>
> Hi,
>
> If I write a system program which has Python >= 3.y as a dependency,
> what are the options for someone whose Linux distribution provides
> Python 3.x, where x < y?
>
> I am aware that an individual user could use (mini)conda to install a
> more recent version of Python in his/her home directory, but I am
> interested in how root would install such a program.
>
> Cheers,
>
> Loris
>
> --
> This signature is currently under constuction.
> --
> https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!l02A4qczH46l1ScA8yisiIwlDKh96sy16woPSOSABWqym4b6dBtHzExfFwZsnPDezDwDqaM0fdCMs3080WQQZ-b5OghOOpI$
-- 
Dr. Loris Bennett (Herr/Mr)
ZEDAT, Freie Universität Berlin
-- 
https://mail.python.org/mailman/listinfo/python-list


RE: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread David Raymond
> Then I'm very confused as to how things are being done, so I will shut
> up. There's not enough information here to give performance advice
> without actually being a subject-matter expert already.

Short version: In this specific case "weights" is a 5,147 element list of 
floats, and "input" is a 10 element list of integers which has the indexes of 
the 10 elements in weights that he wants to add up.

sum_ = 0
for key in input:
sum_ += weights[key]

vs

sum_ = sum(weights[key] for key in input)

vs... other ways
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: =- and -= snag

2023-03-15 Thread Morten W. Petersen
I don't remember making such a mistake ever before, but it might have
happened. -= is a convenient operator so I've probably used it a lot.

Anyway, I found that flake8 flagged this as

E225 missing whitespace around operator

and it's the only linter of pylint, flake8 and pyflake that detects this.

Regards,

Morten

On Wed, Mar 15, 2023 at 5:32 AM Gilmeh Serda
 wrote:

> On Mon, 13 Mar 2023 22:26:20 +0100, Morten W. Petersen wrote:
>
> > numbers for calculations didn't add up.  It went into negative numbers,
> > when that shouldn't have been possible.
>
> We have all written code that makes us wonder why the compiler even
> bothered with it and didn't give up on the first line.
>
> --
> Gilmeh
>
> If this fortune didn't exist, somebody would have invented it.
> --
> https://mail.python.org/mailman/listinfo/python-list
>


-- 
I am https://leavingnorway.info
Videos at https://www.youtube.com/user/TheBlogologue
Twittering at http://twitter.com/blogologue
Blogging at http://blogologue.com
Playing music at https://soundcloud.com/morten-w-petersen
Also playing music and podcasting here:
http://www.mixcloud.com/morten-w-petersen/
On Google+ here https://plus.google.com/107781930037068750156
On Instagram at https://instagram.com/morphexx/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread Chris Angelico
On Thu, 16 Mar 2023 at 02:14, Thomas Passin  wrote:
>
> On 3/15/2023 11:01 AM, Chris Angelico wrote:
> > On Thu, 16 Mar 2023 at 01:26, David Raymond  
> > wrote:
> >> I'm not quite sure why the built-in sum functions are slower than the for 
> >> loop,
> >> or why they're slower with the generator expression than with the list 
> >> comprehension.
> >
> > For small-to-medium data sizes, genexps are slower than list comps,
> > but use less memory. (At some point, using less memory translates
> > directly into faster runtime.) But even the sum-with-genexp version is
> > notably faster than reduce.
> >
> > Is 'weights' a dictionary? You're iterating over it, then subscripting
> > every time. If it is, try simply taking the sum of weights.values(),
> > as this should be significantly faster.
>
> It's a list.
>

Then I'm very confused as to how things are being done, so I will shut
up. There's not enough information here to give performance advice
without actually being a subject-matter expert already.

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


Re: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread Thomas Passin

On 3/15/2023 11:01 AM, Chris Angelico wrote:

On Thu, 16 Mar 2023 at 01:26, David Raymond  wrote:

I'm not quite sure why the built-in sum functions are slower than the for loop,
or why they're slower with the generator expression than with the list 
comprehension.


For small-to-medium data sizes, genexps are slower than list comps,
but use less memory. (At some point, using less memory translates
directly into faster runtime.) But even the sum-with-genexp version is
notably faster than reduce.

Is 'weights' a dictionary? You're iterating over it, then subscripting
every time. If it is, try simply taking the sum of weights.values(),
as this should be significantly faster.


It's a list.

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


Re: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread Thomas Passin

On 3/15/2023 10:24 AM, David Raymond wrote:

Or use the sum() builtin rather than reduce(), which was
*deliberately* removed from the builtins. The fact that you can get
sum() without importing, but have to go and reach for functools to get
reduce(), is a hint that you probably shouldn't use reduce when sum
will work.


Out of curiosity I tried a couple variations and am a little confused by the 
results. Maybe I'm having a brain fart and am missing something obvious?

Each of these was run with the same "data" and "perceptrons" values to keep 
that fair.
Times are averages over 150 iterations like the original.
The only thing changed in the trainPerceptron function was how to calculate sum_


Original:
sum_ = 0
for key in input:
 v = weights[key]
 sum_ += v
418ms

The reduce version:
sum_ = reduce(lambda acc, key: acc + weights[key], input)
758ms

Getting rid of the assignment to v in the original version:
sum_ = 0
for key in input:
 sum_ += weights[key]
380ms

But then using sum seems to be slower

sum with generator expression:
sum_ = sum(weights[key] for key in input)
638ms

sum with list comprehension:
sum_ = sum([weights[key] for key in input])
496ms

math.fsum with generator expression:
sum_ = math.fsum(weights[key] for key in input)
618ms

math.fsum with list comprehension:
sum_ = math.fsum([weights[key] for key in input])
480ms


I'm not quite sure why the built-in sum functions are slower than the for loop,
or why they're slower with the generator expression than with the list 
comprehension.


I tried similar variations yesterday and got similar results.  All the 
sum() versions I tried were slower.  Like you, I got the smallest times for


> for key in input:
>  sum_ += weights[key]

but I didn't get as much of a difference as you did.

I surmise that in using the sum() variations, that the entire sequence 
was constructed first, and then iterated over.  In the non-sum() 
versions, no new sequence had to be constructed first, so it would make 
sense for the latter to be slower.

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


Re: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread Chris Angelico
On Thu, 16 Mar 2023 at 01:26, David Raymond  wrote:
> I'm not quite sure why the built-in sum functions are slower than the for 
> loop,
> or why they're slower with the generator expression than with the list 
> comprehension.

For small-to-medium data sizes, genexps are slower than list comps,
but use less memory. (At some point, using less memory translates
directly into faster runtime.) But even the sum-with-genexp version is
notably faster than reduce.

Is 'weights' a dictionary? You're iterating over it, then subscripting
every time. If it is, try simply taking the sum of weights.values(),
as this should be significantly faster.

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


RE: Debugging reason for python running unreasonably slow when adding numbers

2023-03-15 Thread David Raymond
> Or use the sum() builtin rather than reduce(), which was
> *deliberately* removed from the builtins. The fact that you can get
> sum() without importing, but have to go and reach for functools to get
> reduce(), is a hint that you probably shouldn't use reduce when sum
> will work.

Out of curiosity I tried a couple variations and am a little confused by the 
results. Maybe I'm having a brain fart and am missing something obvious?

Each of these was run with the same "data" and "perceptrons" values to keep 
that fair.
Times are averages over 150 iterations like the original.
The only thing changed in the trainPerceptron function was how to calculate sum_


Original:
sum_ = 0
for key in input:
v = weights[key]
sum_ += v
418ms

The reduce version:
sum_ = reduce(lambda acc, key: acc + weights[key], input)
758ms

Getting rid of the assignment to v in the original version:
sum_ = 0
for key in input:
sum_ += weights[key]
380ms

But then using sum seems to be slower

sum with generator expression:
sum_ = sum(weights[key] for key in input)
638ms

sum with list comprehension:
sum_ = sum([weights[key] for key in input])
496ms

math.fsum with generator expression:
sum_ = math.fsum(weights[key] for key in input)
618ms

math.fsum with list comprehension:
sum_ = math.fsum([weights[key] for key in input])
480ms


I'm not quite sure why the built-in sum functions are slower than the for loop,
or why they're slower with the generator expression than with the list 
comprehension.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: We can call methods of parenet class without initliaze it?

2023-03-15 Thread Roel Schroeven

Op 15/03/2023 om 10:57 schreef scruel tao:

The following code won’t be allowed in Java, but in python, it works fine:
```python
class A:
 A = 3

 def __init__(self):
 print(self.A)

 def p(self):
 print(self.A)
 self.A += 1


class B(A):
 def __init__(self):
 print(2)
 self.p()
 super().__init__()


B()
```

How can I understand this? Will it be a problem?
Important: __init__ is not a constructor, like you have for example in 
C++. I don't know Java, but it seems plausible it works somewhat like 
C++ in this regard. Python does it differently: when you create an 
instance, the instance is fully created/constructed even before __init__ 
is called. __init__ is purely an initializer: you can use to initialize 
the things you want to initialize.


Back to your example: it works because A is a class-level attribute, 
which is initialized independently from __init__. If you make it an 
instance attribute, like below, things stop working:


    class A:
    def __init__(self):
    self.A = 3
    print(self.A)

    def p(self):
    print(self.A)
    self.A += 1


    class B(A):
    def __init__(self):
    print(2)
    self.p()
    super().__init__()


    B()
    print(A.A)

That fails like this:

    Traceback (most recent call last):
  File ".code.tio", line 18, in 
    B()
  File ".code.tio", line 14, in __init__
    self.p()
  File ".code.tio", line 7, in p
    print(self.A)
    AttributeError: 'B' object has no attribute 'A'

That's because now A is indeed initialized in A.__init__, so it doesn't 
exist before A.__init__ is called.


--
"Too often we hold fast to the cliches of our forebears. We subject all
facts to a prefabricated set of interpretations. Too often we enjoy the
comfort of opinion without the discomfort of thought."
-- John F Kennedy

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


Re: Tkinter and cv2: "not responding" popup when imshow launched from tk app

2023-03-15 Thread John O'Hagan
On Tue, 2023-03-14 at 16:22 -0400, aapost wrote:
> On 3/14/23 06:54, John O'Hagan wrote:

[...]
> > 
> > Here is minimal code that demonstrates the problem in the subject
> > line:
> > 
> > import cv2
> > from tkinter import *
> > 
> > images=['a.jpg', 'b.jpg', 'c.jpg'] #change to image paths
> > 
> > cv2.namedWindow('W', cv2.WND_PROP_FULLSCREEN)
> > cv2.setWindowProperty('W', cv2.WND_PROP_FULLSCREEN,
> > cv2.WINDOW_FULLSCREEN)
> > counter=[0]
> > def show():
> >     cv2.imshow('W', cv2.imread(images[counter[0] % len(images)]))
> >     cv2.waitKey(1)
> >     counter[0] += 1
> > 
> > root=Tk()
> > root.wm_attributes("-topmost", 1)
> > Button(root, text=' Show ', command=show).pack()
> > mainloop()
> > 
> > It works up to a point - I can cycle through the images by clicking
> > the
> > button - but if I mouse-click on the displayed image (e.g. to use
> > the
> > zooming and panning features of cv2), nothing happens, and a few
> > seconds later the image greys out and a popup appears saying
> > "'Unknown'
> > is not responding" and giving the option of waiting or forcing
> > close
> > (but sometimes these options are greyed out too). Clicking "wait",
> > if
> > available, closes the popup but it comes back a few seconds later.
> > If I
> > then click on the tkinter window titlebar, the popup changes
> > to "'Tk'
> > is not responding". Clicking on the button still works and after a
> > few
> > clicks the popup closes.

[...]

> > I think this particular popup is a Gnome thing, but AIUI most DEs
> > have
> > something similar to detect stuck apps. But the app is not stuck.
> > 
> > I suspect this is some kind of interaction between the call to
> > cv2.waitKey (which is necessary but I've never understood why!) and
> > the
> > tkinter event loop, but it's beyond my knowledge.
> > 
> > Any suggestions about causes or workarounds?
> > 
> > Thanks
> > 
> > --
> > 
> > John
> > 
> > 
> 
> 
> I don't get any of the zoom/panning behavior with waitKey(1). But a 
> couple notes from the web:
> 
> 
> https://docs.opencv.org/2.4/modules/highgui/doc/user_interface.html
> 
> Note
> 
> This function should be followed by waitKey function which displays
> the 
> image for specified milliseconds. Otherwise, it won’t display the
> image. 
> For example, waitKey(0) will display the window infinitely until any 
> keypress (it is suitable for image display). waitKey(25) will display
> a 
> frame for 25 ms, after which display will be automatically closed.
> (If 
> you put it in a loop to read videos, it will display the video 
> frame-by-frame)
> 
> https://pythonexamples.org/python-opencv-imshow/
> 
> cv2.waitKey(0) is important for holding the execution of the python 
> program at this statement, so that the image window stays visible. If
> you do not provide this statement, cv2.imshow() executes in fraction
> of 
> a second and the program closes all the windows it opened, which
> makes 
> it almost impossible to see the image on the window.
> 
> if I change waitKey to 0, I get the ability to zoom/pan, but it
> places 
> the tk window in a blocked state because it is waiting on cv2 to
> return. 
> If I hit the ESC key, it releases the wait and gives control back to
> the 
> tk window, allowing me to press show again to continue to the next
> image.
> 
> I can try to change waitKey to a high ms like 1000 and have
> zoom/pan 
> for that amount of time before it gives control back to tk (not a 
> sensical approach).
> 
> The fact that you can still see the image after tk takes back control
> is 
> I believe just a matter of design, some examples show 
> cv2.destroyAllWindows() after waitKey(0) to clean that up, but of
> course 
> if you are reusing the same window, that destroys the target.
> 
> You can resolve that if you move
> cv2.namedWindow('W', cv2.WND_PROP_FULLSCREEN)
> cv2.setWindowProperty('W', cv2.WND_PROP_FULLSCREEN,
> cv2.WINDOW_FULLSCREEN)
> 
> to inside the show, and destroy it after the wait, and make waitKey
> 0, 
> this allows creation/cleanup of that window per image
> 
> Hitting ESC when done zooming/panning on each image to get back to
> tk.

Thanks for your reply.

I'm afraid in the real app it won't be practical to have no gui control
while viewing images.

But your suggestions have made me realise that my issue has nothing to
do with tkinter, it seems to be the way imshow is supposed to work.
This code gives the same behaviour described above:

cv2.imshow('W', array)
cv2.waitKey(100)
time.sleep(20)

I've seen the docs you mention that say the window will close if no
keypress happens within the waitKey time, but that doesn't seem to be
what happens as you say. After waitKey returns, the image remains and
everything works, but for some reason the desktop complains about an
unresponsive app.

You can use cv2 to display video with:

while 1:
 frame = camera.read() #pseudocode
 cv2.imshow('W', frame)
 cv2.waitKey(1)

(In fact this used to work without waitKey if you called
cv2.startWindowThread() after creat

Re: Distributing program for Linux

2023-03-15 Thread Anssi Saari
"Loris Bennett"  writes:

> I am aware that an individual user could use (mini)conda to install a
> more recent version of Python in his/her home directory, but I am
> interested in how root would install such a program.

Root would install the script and required Python version somewhere
depending any site specific practices and then use things like pyenv,
stow, environment modules or whatever to give the users access to it.

Root might even package your script with the interpreter required into
one binary. See Tools/freeze in the source distribution.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: We can call methods of parenet class without initliaze it?

2023-03-15 Thread Greg Ewing via Python-list

On 15/03/23 10:57 pm, scruel tao wrote:

How can I understand this? Will it be a problem?


I can't remember any details offhand, but I know I've occasionally
made use of the ability to do this. It's fine as long as the method
you're calling doesn't rely on anything you haven't initialised yet.

--
Greg


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


We can call methods of parenet class without initliaze it?

2023-03-15 Thread scruel tao
The following code won’t be allowed in Java, but in python, it works fine:
```python
class A:
A = 3

def __init__(self):
print(self.A)

def p(self):
print(self.A)
self.A += 1


class B(A):
def __init__(self):
print(2)
self.p()
super().__init__()


B()
```

How can I understand this? Will it be a problem?
-- 
https://mail.python.org/mailman/listinfo/python-list