9

I couldn't find answer after having read all the following:

Rationale:
When a test script which uses relative imports is being run without -m option I could print a warning message instead of leaving user with standard traceback leading to ValueError: Attempted relative import in non-package exception. Without knowing this I can catch this exception and only suggest lack of -m option could be the reason of error.

1
  • 1
    What do you need it for? Could you give some example or a test case in which this need becomes apparent? Commented Dec 1, 2011 at 21:46

2 Answers 2

3

Disclaimer: this is just an observation, I have not seen it in the docs so it is probably implementation dependent and might not be consistent across different Python versions.

I have noticed that when calling a script using a -m option a variable called __loader__ is added to the namespace, so at the top of your script you could check for existence of that variable:

if '__loader__' in globals():
    # called with -m

For some extra safety you could check to see if __loader__ is an instance of pkgutil.ImpLoader:

if '__loader__' in globals() and __loader__.__class__.__name__ == 'ImpLoader':
Sign up to request clarification or add additional context in comments.

5 Comments

This is in the docs of runpy module; The special global variables __name__, __file__, __loader__ and __package__ are set in the globals dictionary before the module code is executed (Note that this is a minimal set of variables - other variables may be set implicitly as an interpreter implementation detail). However __loader__ is kind of generic and we never know what else might set it someday...
@RaymondHettinger Is there any reason there's no really unique global variable set in this situation?
The only guaranteed unique variables are None and __debug__; however, any double underscored name is treated as reserved for creation by core developers, so __loader__ is somewhat safe (or at least as safe as __name__=='__main__'). If it keeps you up at night, it is alway possible to introspect the object to validate the match.
I'm curious why you didn't use isinstance?
@PiotrDobrogost - pkgutil.ImpLoader is not a part of the namespace, it would need to be imported first. That is another option though.
2

Another observation is that __package__ is set to None when executing the script directly and to the package name when using -m (using the empty string when the module isn't included in any package, so it's still different from None).

1 Comment

Nice! It's not only observation as this is mandated by PEP 366 Main module explicit relative imports.

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.