2

I am trying to improve a set of python files written by a co-worker. There are many scripts and each script calls all the functions and classes from other files

from file1.py import *
from file2.py import *
...

And at times it gets complicated to figured out where the functions are defined. Is there a short way to find the location of functions? And also their definitions? Also, if possible, where a variable is being used? I use VSCode.

5
  • 4
    This is one reason from ... import * is frowned upon. As you figure out, for example, that foo comes from file1, do one of two things: 1) add from file1 import foo, or 2) add import file1 and use file1.foo. Once you are sure you have accounted for everything from file1, get rid of from file1 import * altogether. Commented Jan 10, 2020 at 16:36
  • 1
    You've probably tried this already, but does right-clicking on an identifier name and selecting "Go to Definition" not work? Commented Jan 10, 2020 at 16:38
  • 1
    You don't get a ModuleNotFoundError for file1.py? I'm not sure that's the proper syntax there... I would have used import file1 as f1. But I digress. VSCode should have "Go to definition" and "Go to references" in the context menu when you right click on the functions. Commented Jan 10, 2020 at 16:39
  • @chepner For a language that promotes "Explicit is better than implicit", I'm honestly surprised at the amount of people I see that uses star imports, especially some in widely used packages. Commented Jan 10, 2020 at 16:41
  • 1
    I tried go to definition. Did not get errors nor a response. Overall, there's a lot I have to change. Commented Jan 10, 2020 at 16:42

2 Answers 2

2

So I've been in this exact scenario, and my process was as follows:

Scenario where file2.py includes statements like from file1 import *.

  1. In file1.py, I would copy all the import statements, and paste them in file2.py
  2. I would copy all the top-level function/class names, and set them up as comma-delimited, and replace the * in file2.py: from file1 import file1_method1, file1_method2, file1_class1.
    I don't have VS Code, but I'm sure there's a way to look at the File Structure view and copy the list and reformat it into the import statement.
  3. Repeat steps 1-2 for every from x import *, it's best to start from core files, and then work your way out to dependent files (reduce work for nested import * statements)
  4. Search file2.py for any eval() statements which may reference other modules, and manually import those. If no eval(), then skip.
  5. Optional: Sort the import statements (yay OCD!)
  6. Once this is done, I let the linter work, and remove all unused references (including duplicate imports) except those needed by eval, perhaps add comment for linter to ignore these.
  7. Run your code, and pray you didn't make mistakes (nothing to worry if you didn't!)
  8. Repeat 1-7 for every file in your application!
  9. ???
  10. Profit!

This has been tough, but really has been worth it after all that work to trace what is being used and where in each file.

Sign up to request clarification or add additional context in comments.

Comments

1

If you want to know where a particular function comes from, I think you can find the module using the __module__ property. You could use:

print(myFunction.__module__)

To get the file it has been imported from. You can then use:

print(myModule.__file__) 

To work out the path to the file the module is from.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.