Skip to content

More import fixes for cx_freeze#1801

Closed
fbordignon wants to merge 4 commits intopyqtgraph:masterfrom
fbordignon:import_fixes
Closed

More import fixes for cx_freeze#1801
fbordignon wants to merge 4 commits intopyqtgraph:masterfrom
fbordignon:import_fixes

Conversation

@fbordignon
Copy link
Copy Markdown
Contributor

Related to #1303 for windows. @berr was working on this and forgot to open a PR for the latest commit on his fork from last year. cx_Freeze is going strong.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented May 24, 2021

CI says no 😆

looks like pg.time() has some sort of name conflict that needs addressing. Would have to look into the other failure a bit more.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented May 24, 2021

thanks for hte PR @fbordignon ... pyqtgraph has had some minor annoyances involving freezing applications such as cx_freeze and pyinstaller. Another one that gets me frequently is the use of template files:

pyqtgraph-pyside2_515-py38 ❯ find pyqtgraph -iname "*template*.py" -type f
pyqtgraph/imageview/ImageViewTemplate_pyqt6.py
pyqtgraph/imageview/ImageViewTemplate_pyside2.py
pyqtgraph/imageview/ImageViewTemplate_pyside6.py
pyqtgraph/imageview/ImageViewTemplate_pyqt5.py
pyqtgraph/flowchart/FlowchartCtrlTemplate_pyside6.py
pyqtgraph/flowchart/FlowchartCtrlTemplate_pyside2.py
pyqtgraph/flowchart/FlowchartCtrlTemplate_pyqt5.py
pyqtgraph/flowchart/FlowchartTemplate_pyqt6.py
pyqtgraph/flowchart/FlowchartTemplate_pyqt5.py
pyqtgraph/flowchart/FlowchartTemplate_pyside6.py
pyqtgraph/flowchart/FlowchartTemplate_pyside2.py
pyqtgraph/flowchart/FlowchartCtrlTemplate_pyqt6.py
pyqtgraph/GraphicsScene/exportDialogTemplate_pyside2.py
pyqtgraph/GraphicsScene/exportDialogTemplate_pyside6.py
pyqtgraph/GraphicsScene/exportDialogTemplate_pyqt5.py
pyqtgraph/GraphicsScene/exportDialogTemplate_pyqt6.py
pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyside2.py
pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyqt6.py
pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyside6.py
pyqtgraph/graphicsItems/PlotItem/plotConfigTemplate_pyqt5.py
pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyqt5.py
pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyside6.py
pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyside2.py
pyqtgraph/graphicsItems/ViewBox/axisCtrlTemplate_pyqt6.py
pyqtgraph/canvas/TransformGuiTemplate_pyside6.py
pyqtgraph/canvas/TransformGuiTemplate_pyside2.py
pyqtgraph/canvas/TransformGuiTemplate_pyqt5.py
pyqtgraph/canvas/CanvasTemplate_pyqt6.py
pyqtgraph/canvas/TransformGuiTemplate_pyqt6.py
pyqtgraph/canvas/CanvasTemplate_pyqt5.py
pyqtgraph/canvas/CanvasTemplate_pyside2.py
pyqtgraph/canvas/CanvasTemplate_pyside6.py
pyqtgraph/console/template_pyqt5.py
pyqtgraph/console/template_pyside2.py
pyqtgraph/console/template_pyqt6.py
pyqtgraph/console/template_pyside6.py

The freezing applications seem to miss these (due to how we handle their imports); so I'm definitely in support of making pyqtgraph a bit more robust in that regard.

@fbordignon
Copy link
Copy Markdown
Contributor Author

Yeah, I've just finished working around the missing template files:

import pyqtgraph
pg_folder = Path(pyqtgraph.__file__).parent
templates = pg_folder.rglob("*pyside2.py")
sources = [str(w) for w in templates]
destinations = ["lib"+str(w).replace(str(pg_folder.parent), '') for w in sources]
for a in zip(sources, destinations):
    include_files.append(a)

...

build_options = {
    "packages": [],
    "includes": [],
    "excludes": [],
    "zip_exclude_packages": "*",
    "zip_include_packages": "",
    "include_files": include_files,
    "include_msvcr": True,
    "build_exe": "../build",
}

It will copy as .py files and not .pyc, but it works for now.

@fbordignon
Copy link
Copy Markdown
Contributor Author

Do you think it is Ok to include this hack into the cx_freeze example or is it too hacky?
Need to modify the pattern to get all the templates, as you did on your 'find'.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented May 24, 2021

Do you think it is Ok to include this hack into the cx_freeze example or is it too hacky?

Sounds like par for the course here, I think that would be a welcome addition!

I'm in the middle of trying to wrap up (and expand) PR 1796 so I'm not sure how much help I'll be with dealing with the CI errors this PR has caused for the coming days/week.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Aug 1, 2021

I rebased master onto this branch; and I modified PlotAutoRange.py to use perf_counter (which it should have been doing anyway); and the test suite passes...but I'm not sure we want to use this change. We recently merged #1846 authored by @pijyoi that aimed to reduce the namespace clutter, and this diff, as advertised would sort of undo that change.

That said, freeze applications do need a way of knowing to grab stuff; and we shouldn't be dependent on on people tweaking hooks/config files to make sure they package correctly with greater ease.

I do want to get this working a bit better, and I suspect there is a way we can do this w/o polluting the top level namespace too much.

Actually, I'm curious if #1846 may have fixed this issue in general. @fbordignon could you try and verify it's still a problem based on the 0.12.2 release (or current master branch)?

@ksunden
Copy link
Copy Markdown
Contributor

ksunden commented Aug 1, 2021

defining __all__ for a few files will go a long way, here, I bet

@fbordignon
Copy link
Copy Markdown
Contributor Author

I rebased master onto this branch; and I modified PlotAutoRange.py to use perf_counter (which it should have been doing anyway); and the test suite passes...but I'm not sure we want to use this change. We recently merged #1846 authored by @pijyoi that aimed to reduce the namespace clutter, and this diff, as advertised would sort of undo that change.

That said, freeze applications do need a way of knowing to grab stuff; and we shouldn't be dependent on on people tweaking hooks/config files to make sure they package correctly with greater ease.

I do want to get this working a bit better, and I suspect there is a way we can do this w/o polluting the top level namespace too much.

Actually, I'm curious if #1846 may have fixed this issue in general. @fbordignon could you try and verify it's still a problem based on the 0.12.2 release (or current master branch)?

Hy @j9ac9k. thanks for the update. The master branch at a472f8c does not fix the issue. The error message when freezing the application still is:

pyqtgraph\functions.py', line 21 in <module>
from . import debug, reload
ImportError: cannot import name 'debug' from partially initialized module 'pyqtgraph' (most likely due to a circular import)

@ksunden, defining __all__ for the affected classes can solve this? The goal is to prevent namespace pollution and allow for from .debug import * for example?

@NilsNemitz
Copy link
Copy Markdown
Contributor

NilsNemitz commented Aug 2, 2021

@fbordignon , is it actually necessary to import * from debug in order to make cx_freeze work again? Or is the main thing to ensure that there is an import in __init__.py ?

I think the point of #1846 was to more carefully consider what needs to be part of the main pg.(???) namespace and what can be called as pg.module.(???).

The debug module comes with a huge number of functions/classes, but these would normally be used as e.g. prof = debug.Profiler(), so that import debug (rather than from debug import *) would be sufficient.

But I don't know if that is enough to make cx_freeze happy. :)

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Aug 2, 2021

@fbordignon Thanks for following up. Can you provide some step-by-step instructions to replicate the issue as part of some minimum example? In case you need a dummy app to try and freeze, may I recommend using one of the examples?

As I said, I am motivated to fix this, but I need to try and find a way of doing so without polluting the namespace. There is likely a solution here that will work for all cases.

@pijyoi
Copy link
Copy Markdown
Contributor

pijyoi commented Oct 20, 2021

A possible alternate solution would be to use a single generated file (with a minor edit) usable for all bindings.
For that, the PyQt6 generated file is the only one that is suitable as it is the only one that uses the long enum spellings.

The minor edit required would be changing

from PyQt6 import QtCore, QtGui, QtWidgets

to: (number of dots varies)

from ...Qt import QtCore, QtGui, QtWidgets

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 20, 2021 via email

@fbordignon
Copy link
Copy Markdown
Contributor Author

Turns out the original issue with cx_freeze and statements like from . import debug seems to be fixed on the latest version of cx_freeze. The problem was that those statements were not adding the modules to the dependencies and they were not frozen to the app. I did not find the issue related to that in cx_freeze, but it is working now.
Now the frozen app works without even the original fix merged on #1303 I've pushed a commit reverting the issue.

Oops, I was testing the issue and accidentally pushed changes to SignalProxy.py as well. May not change anything but if needed I can revert it.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 20, 2021

Hi @fbordignon if I'm reading the PR and your comment right, the only diff you're proposing is removing this bit from __init__.py ?

from .ThreadsafeTimer import *

@fbordignon
Copy link
Copy Markdown
Contributor Author

Yes, this change from .ThreadsafeTimer import * was merged with issue #1303 and it is no longer needed for newer cx_freeze versions. This current issue #1801 is fixed by the cx_freeze update to 6.8.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 20, 2021

Implementing this change would break things like...

import pyqtgraph as pg

...

obj = pg.ThreadSafetimer()

@outofculture you were using this very object in ACQ4, I imagine this change would impact you?

@fbordignon does cx_freeze 6.8+ work w/ pyqtgraph as it is on master (or 0.12.3) as is?

@fbordignon
Copy link
Copy Markdown
Contributor Author

fbordignon commented Oct 20, 2021

@fbordignon does cx_freeze 6.8+ work w/ pyqtgraph as it is on master (or 0.12.3) as is?

Yes it does. The removal I am proposing is only to revert the changes made on issue #1303 and completely optional. If it is to break something I think we can close this issue and do nothing.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Oct 20, 2021

@fbordignon does cx_freeze 6.8+ work w/ pyqtgraph as it is on master (or 0.12.3) as is?

Yes it does. The removal I am proposing is only to revert the changes made on issue #1303 and completely optional. If it is to break something I think we can close this issue and do nothing.

Cool, I'm leaning on closing this PR as things are working. Merging the change as-is could have some breakages I think as the previous change added an object to the namespace... but I'll wait to hear from people that actually use the ThreadSafeTimer to chime in 👍🏻

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Nov 18, 2021

Hi @fbordignon I finally got ahold of some folks that I thought might be impacted by this PR, they gave it a thumbs up. I see we've created some merge conflicts for you. Would you mind if I resolved the conflicts and then merged this?

@fbordignon
Copy link
Copy Markdown
Contributor Author

@j9ac9k I just did, but I believe the changes I've proposed were on master already. Please close this PR without merging since the change that remains does nothing.

@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Nov 18, 2021

I still see ThreadSafeTimer being imported in __init__.py. Regardless, I can close out the PR. Thanks for the follow up here, I'm glad to hear cx_freeze is working w/ pyqtgraph.

@fbordignon
Copy link
Copy Markdown
Contributor Author

fbordignon commented Nov 18, 2021

Ok, Maybe I messed things on the merge with master. I did not see I was overwriting the from .ThreadSafeTimer import *
Let me give another go

@fbordignon
Copy link
Copy Markdown
Contributor Author

Yeah, the only change is that line now on the diff to master. It does not impact a lot because there is an all defined inside ThreadSafeTimer so I believe it is OK to leave it and do not merge. ThreadSafeTimer.py is fairly small anyways so no harm.

The whole ordeal was me trying to merge imports defined at 6eeb0b5

from .debug import *
from .reload import *

which were needed to freeze an app on a previous version of cx_freeze but were polluting the namespace.
Now it is everything working properly with newer versions of cx_freeze.

@fbordignon fbordignon closed this Nov 18, 2021
@j9ac9k
Copy link
Copy Markdown
Member

j9ac9k commented Nov 18, 2021

Sorry for the very delayed follow up; really appreciate your prompt responses. Please don't hesitate to reach out of pyqtgraph is not meeting some criteria regarding being frozen and such (or any other issue w/ the library) 👍🏻

@fbordignon
Copy link
Copy Markdown
Contributor Author

Nothing to be sorry about, your responses were always on point. It is me that should be thanking you guys for such a great lib!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants