Terminate importation of module non-fatally?

2020-06-25 04:57发布

I'd like use if __name__ != '__main__': and then end the execution of a script at that point when it's being imported, rather than doing the usual if __name__ == '__main__': and indentation of all the rest of the code in the file.

However I have been unable to determine what would cause only this to happen and not have other undesirable side-effects. sys.exit() stops the whole interpreter and all the other things I've tried either raise some sort of exception or are illegal.

Update:

I've selected @trutheality's answer because it accomplishes what I want and is extremely easy to start using. That said, I thought several of the other answers very interesting and/or clever -- thanks to all who responded -- and plan on investigating some of them further as time permits. I had no idea doing what I want could get so involved.

标签: python import
4条回答
ら.Afraid
2楼-- · 2020-06-25 05:07

main.py

try:
   import foo
except:
    print "Failed to import foo"

foo.py

At top of file

if __name__ != "__main__":
   raise RunTimeError("foo must be run as main, not as a module.")

class foo(Object):
   pass

Since python processes a file sequentially, then class Foo would not be defined.

Another thought would be to overload the import logic itself via PEP 302

查看更多
男人必须洒脱
3楼-- · 2020-06-25 05:11

Best solution IMO: have two files.

module_main.py

import actual_module.py

if __name__ != '__main__':
    raise RunTimeError("You should be importing actual_module.py, not module_main.py")

# Your "main" code

actual_module.py

# Actual module code (classes, functions, etc)

This is "clean" in the sense that an exception is thrown only when something is actually wrong -- no one should ever import module_main.py, they should import actual_module.py.

April Fools solution

If you're using python 2.3 there is a goto module from entrian, that apparently works! It was made as an April fools joke, and should never be used, (if you look at the source you'll see why: it adds a lot of overhead) but as a proof of concept it seems like the only way I can find to accomplish what you want in any sort of concise way.

from goto import goto, label

# Code that should always be imported (classes etc.)

if __name__ != "__main__":
    goto .end

# Stuff to be executed when this is main, NOT indented

label .end
查看更多
我只想做你的唯一
4楼-- · 2020-06-25 05:14

Another Hack:

# code

if __name__ == "__main__": exec("""

# main code

#""")

So... you've lost the indentation, but also the syntax highlighting and any other features of the editor you were using, unless you comment out the if line every time you edit.

查看更多
ゆ 、 Hurt°
5楼-- · 2020-06-25 05:17

Very similar to my original answer but slightly scarier

partialimport.py

class PartialImport(Exception):
    def __init__(self, locals, msg = ""):
        self.module = locals

main.py

from partialimport import PartialImport
try:
   import foo
except PartialImport, e:
    #Note e.module and therefore foo will be a Dict and not a module instance!
    foo = e.module

foo.py

from partialimport import PartialImport

class Boo:
    pass

if __name__ != "__main__":    
    raise PartialImport(locals())

class Foo:
    pass

Disclaimer

This is a fantastically terrible hack that will increase the likelihood of your peers murdering you, but this does work.

查看更多
登录 后发表回答