4

I am trying to use a library that creates objects, and adds them to the global namespace at runtime.

PyCharm cannot find the references to the objects, because they aren't originally in the namespace.

How can I get PyCharm introspection to not complain "Cannot find reference..."? I don't want to use noinspection tags.


Sample Code

To help make my question clear, I have drawn up sample code of using an object created at runtime in PyCharm.

main.py

from some_import import some_obj_1


if __name__ == "__main__":
    print(f"obj_1.some_attr = {some_obj_1.some_attr}")

some_import.py

class SomeClass:
    def __init__(self, attr_init: int = 0):
        self.some_attr = attr_init


globals()["some_obj_1"] = SomeClass(1)

Output of running main.py:

obj_1.some_attr = 1

What I see in PyCharm:

main.py view


Relevant Articles

Dynamic runtime type inference in PyCharm 2.7

This article suggests enabling Collect run-time types information for code insight. However, enabling this settings and running the debugger did not solve my problem.


Possible Solutions

  • Making a PyCharm stub file
  • Suppressing the error message using PyCharm noinspection tag + a type hint
    • This is "manual", and thus I don't like this solution very much
# noinspection PyUnresolvedReferences
from some_import import some_obj_1, SomeClass

some_obj_1: SomeClass


if __name__ == "__main__":
    print(f"obj_1.some_attr = {some_obj_1.some_attr}")

This was made using Python 3.7.6 and PyCharm 2019.2.5 CE.

Intrastellar Explorer
  • 3,005
  • 9
  • 52
  • 119
  • 5
    There is no way for pycharm to determine such things without running your code. You can either write a stub file, use hardcoded declarations like in your example or write a pycharm plugin that allows you to pass your information to pycharm. For example you could write a pycharm plugin that parses lines that mutate `globals()` – kmaork Feb 28 '20 at 13:37
  • Thank you @kmaork for confirming my readings/intuition! – Intrastellar Explorer Feb 28 '20 at 16:51
  • 1
    Of course, not a solution, but if you know the name of the object that you want to create (like in the example), that is, if the name of the object is not in a variable (like in `globals()[varname] = ...`), then without touching the `main.py`, you can always add the type hint line right after the dynamic creation of the variable in `some_import.py`. – J C Gonzalez Mar 04 '20 at 09:46
  • Good thinking @JCGonzalez! I tested that, and it's a viable solution :). It only works if one can make changes to `some_import.py`. Unfortunately, in my case `some_import.py` is inside a 3rd party pip installable package. – Intrastellar Explorer Mar 04 '20 at 17:23
  • Oops, bad luck... Anyway, as I said it's not a complete solution. Hopefully, somebody will come with a plugin like the one @kmaork pointed at... – J C Gonzalez Mar 05 '20 at 09:07

1 Answers1

-1

The below link makes me think it is possible just by using the module name.

Behaviour of global variables in "run with Python console"

I've written this code but it's tough for me to test as I'm using Spyder and that works with your original attempt

import some_import as si


if __name__ == "__main__":
    print(f"obj_1.some_attr = {si.some_obj_1.some_attr}")
Alistair
  • 589
  • 3
  • 11
  • Hello @Alistair! Thank you for taking a shot. However, this does not work. All it does is move the `Cannot find reference` warning from the import line to be inside the `__main__` code block. – Intrastellar Explorer Mar 05 '20 at 17:54