-
Notifications
You must be signed in to change notification settings - Fork 26.3k
Warn if import torch is called from the source root.
#39995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
💊 CI failures summary and remediationsAs of commit 738ac49 (more details on the Dr. CI page):
2 failures confirmed as flaky and can be ignored:
Extra GitHub checks: 1 failed
ci.pytorch.org: 1 failedcodecov.io: 1 failed
This comment was automatically generated by Dr. CI (expand for details).Follow this link to opt-out of these comments for your Pull Requests.Please report bugs/suggestions on the GitHub issue tracker or post in the (internal) Dr. CI Users group. This comment has been revised 35 times. |
|
Yeah, this test is incomplete; if you are working on a |
ezyang
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too many false positives
|
How about we add some checking at the end of One should be able to do this by checking if |
|
I met the same problem. ``
Would u mind give me some advice? |
The problem is that there is a folder in the pytorch repo named |
Thanks for the advice! I wasn't aware that pytorch could be compiled in situ. I'll try your suggestion; it also has the nice property that it shouldn't have false positives, so I can raise an |
|
@ShawnZhong @ezyang I've switched to a None check of torch._C to avoid false positives. PTAL. |
torch/__init__.py
Outdated
| # Check to see if we can load C extensions, and if not provide some guidance | ||
| # on what the problem might be. | ||
| import torch._C as _C_for_compiled_check | ||
| if _C_for_compiled_check.__file__ is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ShawnZhong Can you point where it is documented what the meaning of __file__ on C extensions is supposed to mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, I don't want to be relying on undocumented "accidents" in Python, for something that is supposed to help users debug. If we're trying to discover user misconfiguration and report against it, the way we test for it needs to be 100% correct; otherwise, we're just making the problem worse when the detection mechanism is wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy:
file is the pathname of the file from which the module was loaded, if it was loaded from a file. The file attribute may be missing for certain types of modules, such as C modules that are statically linked into the interpreter; for extension modules loaded dynamically from a shared library, it is the pathname of the shared library file.
So if torch._C is loaded from a shared library (torch/_C.cpython-37m-x86_64-linux-gnu.so in my case), the __file__ attribute is the pathname of that file. If the file is missing, then torch._C is loaded from the stub folder torch/_C, and gives None for its __file__ attribute.
I am open to alternative methods to check if a module is loaded from C extensions. I have tried ctypes.util.find_library and ctypes.cdll.LoadLibrary but they didn't seem to work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think stub file should ever be loaded; it's a pyi file and I'm pretty sure those get ignored....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, they shouldn't. I am saying that torch._C is loaded from the torch/_C in the absence of the actual shared library file, so there is no ImportError thrown when calling from torch._C import * in __init__.py in that case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Empirically the None check does work. (That's not proof that it's general, of course. But it is not ignored.) And I agree that absent that torch._C will resolve to torch/_C.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. There is no torch/_C/__init__.py file, so you should never resolve to this directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need an __init__ file to resolve an import:
$ mkdir test123
$ python3
>>> import test123
>>> print(test123.__file__)
None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is a new Python 3.3 thing for implicit namespace packages 🤦
|
If I'm trying to build a development copy of PyTorch, and there is an unrelated installation of PyTorch hanging around, usually what I want to do in this situation is uninstall that PyTorch (this is why we often suggest people |
This is trying to solve a different problem, which is the following: That said, if the wording is not clear we should definitely adjust accordingly. |
|
@ezyang What is the status of this? Are you satisfied that the guard works as intended or do you still have concerns? |
|
This PR doesn't seem to solve the stated problem. On a fresh checkout, with no torch installed anywhere: On a fresh checkout, with torch installed via conda (and a copy of |
That's why. |
|
I suppose I should ask the question: why are you running |
I build different setups in different conda environments so that I can quickly switch between them and guarantee isolation. (Especially useful for A/B testing.) |
|
|
|
robieta and I discussed this in VC, and we agreed that we'll simplify the diagnosis code to only give a single error message (that is googleable) and more directly says when this situation could occur (specifically when we have loaded the During this VC robieta explained why he runs |
|
I've simplified the flow per discussion with @ezyang. I like this a lot better, as it is both clearer and more robust. Thanks for the feedback, and let me know what you think of this iteration. |
| # _initExtension is chosen (arbitrarily) as a sentinel. | ||
| from torch._C import _initExtension | ||
| except ImportError: | ||
| import torch._C as _C_for_compiled_check |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to report the import error from line 201, or line 203, when _C is not importable at all? 203 will clobber the original error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I want the one from 203. (I'm not sure it's possible due to the earlier from torch._C import * statements, but for the sake of argument lets say there is a case when it can happen. For now I just mocked it by raising my own ImportError) The traceback contains both:
Traceback (most recent call last):
File "/data/users/taylorrobie/repos/pytorch/torch/__init__.py", line 201, in <module>
from torch._C import _initExtension
ImportError: cannot import name '_initExtension' from 'torch._C' (unknown location)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/data/users/taylorrobie/repos/pytorch/torch/__init__.py", line 204, in <module>
raise ImportError("Imagine this came from `import torch._C as _C_for_compiled_check`")
ImportError: Imagine this came from `import torch._C as _C_for_compiled_check`
Alternatively, if the concern is that the error is complete but confusing we can do a second guard:
try:
import torch._C as _C_for_compiled_check
except ImportError:
raise ImportError("Could not locate the `torch._C` module") from None
(Also, TIL about raise Exception from None for nested exceptions. Definitely going to add that to the primary exception.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Up to you! I think it is a little confusing, but not worth doing something dramatically different
…h/pytorch into gh/taylorrobie/torch_import_guard
Codecov Report
@@ Coverage Diff @@
## master #39995 +/- ##
==========================================
- Coverage 67.84% 67.83% -0.01%
==========================================
Files 384 384
Lines 49984 49992 +8
==========================================
+ Hits 33912 33914 +2
- Misses 16072 16078 +6
Continue to review full report at Codecov.
|
facebook-github-bot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@robieta has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

This is a small developer quality of life improvement. I commonly try to run some snippet of python as I'm working on a PR and forget that I've cd-d into the local clone to run some git commands, resulting in annoying failures like:
ImportError: cannot import name 'default_generator' from 'torch._C' (unknown location)This actually took a non-trivial amount of time to figure out the first time I hit it, and even now it's annoying because it happens just infrequently enough to not sit high in the mental cache.
This PR adds a check to
torch/__init__.pyand warns ifimport torchis likely resolving to the wrong thing:so that the soon to follow internal import failure makes some sense. I elected to make this a warning rather than an exception because I'm not 100% sure that it's always wrong. (e.g. weird
PYTHONPATHorimportlibcorner cases.)EDIT: There are now separate cases for
cwdvs.PYTHONPATH, and failure is anImportError.