sd-webui-controlnet icon indicating copy to clipboard operation
sd-webui-controlnet copied to clipboard

[Bug]: module file conflict

Open vladmandic opened this issue 2 years ago • 29 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues and checked the recent builds/commits of both this extension and the webui

What happened?

i've been fumbling around this, but i cant find solution. problem is if two different extensions have exactly the same internal folders/files.

for example, both controlnet and kohya additional networks perform same import

from scripts import xyz_grid_support

those are different files that are local to each extension. but python loader in its wisdom decides that module is already loaded so what ends up is that whatever extension loads second will try to use module from first loaded extension - and that will of course fail.

i'm really out of ideas.

i'd love to solve this in core, but for the moment easy solution would be to have both extensions have unique module names - can you do that?

anyone with ideas?

link to issue https://github.com/vladmandic/automatic/issues/297

Steps to reproduce the problem

  1. Go to ....
  2. Press ....
  3. ...

What should have happened?

multiple extensions should not create module namespace conflict.

Commit where the problem happens

N/A

What browsers do you use to access the UI ?

Google Chrome

Command Line Arguments

N/A

Console logs

Module load: /home/vlado/dev/automatic/extensions/sd-webui-additional-networks/scripts/additional_networks.py: AttributeError
Traceback (most recent call last) │ /home/vlado/dev/automatic/modules/script_loading.py:10 in load_module                                                                                                                                
│    9 │   try:                                                                                                                                                                                        │ ❱ 10 │   │   module_spec.loader.exec_module(module)                                                                                                                                                  │   11 │   except Exception as e:                                                                                                                                                                      │ in exec_module:883                                                                                                                                                                                   │ in _call_with_frames_removed:241                                                                                                                                                                                                                                                                                                                                                                           │
│ /home/vlado/dev/automatic/extensions/sd-webui-additional-networks/scripts/additional_networks.py:394 in <module>                                                                                     │
│                                                                                                                                                                                                      │   393                                                                                                                                                                                                │ ❱ 394 xyz_grid_support.initialize(Script)                                                                                                                                                            │   395                                                                                                                                                                                                AttributeError: module 'scripts.xyz_grid_support' has no attribute 'initialize'

when adding `print(xyz_grid_support.__file__)`, you can clearly see its the wrong module:
> /home/vlado/dev/automatic/extensions-builtin/sd-webui-controlnet/scripts/xyz_grid_support.py

Additional information

No response

vladmandic avatar Apr 21 '23 04:04 vladmandic

This and #940 are caused by our module paths not being unique. We should prefix the names with lib_controlnet_ or something like that.

ljleb avatar Apr 21 '23 09:04 ljleb

Does python have clever ways to specify folder priority?

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

Yes, by manipulating sys.path I presume. I am not sure if this could break something else unexpectedly again though,and if it can actually work. Going with the unique module names is what most extensions have been doing AFAIK. For example see unprompted's source: https://github.com/ThereforeGames/unprompted/tree/main/lib_unprompted

ljleb avatar Apr 21 '23 09:04 ljleb

It's a bit unfortunate. It feels like every time I commit something, something else unexpectedly breaks. In this case the underlying issue is not even something I wrote code for. The pointer was already null, I just happened to dereference it.

ljleb avatar Apr 21 '23 09:04 ljleb

but how we can change the priority? is sys.path even ordered?

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

Yes sys.path looks for imports in the order the paths are listed. i.e. we could try reordering. Again, I am not convinced this is the way to go and if it can actually fix the problem.

ljleb avatar Apr 21 '23 09:04 ljleb

but this will break other modules to read our scripts

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

wait, if all extensions share the same name "scripts" then how those people use "from scripts import X"

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

why I can use "from scripts import api" without read other extensions' api?

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

I don't know, is it related to the values in sys.path? Put a breakpoint or print its value when loading controlnet.py.

Are there extensions that import the annotator module? I was under the impression most of the dependencies should be inside scripts.

ljleb avatar Apr 21 '23 09:04 ljleb

for example when we

from scripts import global_state, hook, external_code, processor, xyz_grid_support

why this "scripts" is correct?

why it is not other extensions' "scripts". note that all extensions will have "scripts" folder

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

Look at the body of the issue here. It actually has the same rules as outside scripts. i.e. we cannot import xyz_grid_support.

ljleb avatar Apr 21 '23 09:04 ljleb

but if we use something like lib_controlnet_script then A1111 cannot read this. is this problem unsolveable?

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

No we cannot rename scripts. We can try renaming conflicting files inside of it instead.

Maybe for now, don't import and reload annotator_path and xyz_grid_support inside controlnet.py. If we don't import them, we should not get these error like before I presume.

ljleb avatar Apr 21 '23 09:04 ljleb

Unfortunately this means having users reatart the webui from the ground up every time we change these files.

ljleb avatar Apr 21 '23 09:04 ljleb

but if we do not import annotator_path how we can read annotator path?

lllyasviel avatar Apr 21 '23 09:04 lllyasviel

We only started getting reports of annotator being a problematic name when importing it from controlnet.py. I meant to refer to the imports inside controlnet.py.

ljleb avatar Apr 21 '23 09:04 ljleb

what about I remove the importlib.reload(annotator_path) and importlib.reload(xyz_grid_support) for the time now and we consider these later

lllyasviel avatar Apr 21 '23 10:04 lllyasviel

how you think about this? https://github.com/Mikubill/sd-webui-controlnet/pull/951 @ljleb

lllyasviel avatar Apr 21 '23 10:04 lllyasviel

perhaps i just merge?

lllyasviel avatar Apr 21 '23 10:04 lllyasviel

Yes this should resolve this issue. Now we have to make sure to never import these modules directly from controlnet.py, unless we rename them.

ljleb avatar Apr 21 '23 10:04 ljleb

In fact, a possible solution is to replace annotator and xyz_grid_support with forwarding modules:

xyz_grid_support.py:

from lib_controlnet.xyz_grid_support import *

And then just copy the current xyz_grid_support.py file to lib_controlnet, adjusting imports as necessary.

ljleb avatar Apr 21 '23 10:04 ljleb

Then, in controlnet.py we can do:

from lib_controlnet import xyz_grid_support
importlib.reload(xyz_grid_support)

ljleb avatar Apr 21 '23 10:04 ljleb

annotator has super complicated self import in those controlnet's mmcv and controlnet's detectron2

lllyasviel avatar Apr 21 '23 10:04 lllyasviel

it cannot be changed, perhaps ask users to uninstall any package named annotator

lllyasviel avatar Apr 21 '23 10:04 lllyasviel

We can otherwise move the models_path variable to global_state instead. This would allow the settings to be changed on ui reload instead of complete restart.

ljleb avatar Apr 21 '23 10:04 ljleb

For xyz it is possible, I understand the constraints for annotator.

ljleb avatar Apr 21 '23 10:04 ljleb

will consider later

lllyasviel avatar Apr 21 '23 10:04 lllyasviel

I'll open a PR when i'm in front of my pc if it has not yet been fixed.

ljleb avatar Apr 21 '23 10:04 ljleb