What to do when the __name__ shouldn't equal '__main__' - python

I see a lot of people doing
if __name__ == '__main__':
main()
where main() presumably has all the useful code. What if I don't want the script to be imported? It doesn't have useful functions/classes to import. Is it just as elegant to do
if __name__ != '__main__':
sys.exit()
print('this script shouldn\'t be imported')
when your code won't do anything for the outsider?

Unless the code simply won't run correctly when it is imported, I would strongly recommend against adding unnecessary safeguards. Don't treat others like children - let them decide. All you need to do is provide documentation about the correct usage.
In the case that someone should import module A instead of B because of some weird order of execution issue, you could raise an exception with a message directing the user to A. But this really isn't a common scenario.

Don't worry when your code is being imported, but worry if nobody wants to import it! :)
Indeed What for to protect it in such a way?
If one person has you script it can easily fix it and allow importing.
Best way is to let people decide how to import the code: use as a module or a script.

Related

How to import the main function from a Python file not defining "def main" in it?

I am writing a Python (3.5) module in which I'd like to make use of an existing Python module from an open source project. The module I want to import contains:
several functions
a if __name__ == '__main__': instruction
but does not contain a def main(args) function.
Because there is no actual main function, I cannot import it by means of import module and use it as module.main(). Although I did find options to separately execute it as script via the commands os.system() and subprocess.Popen(), I am actually looking for a way to make this call an integral part of my code.
I understand I can add the def main() part myself in the original code, but because it comes from an open source project, I am looking for ways to leave it untouched, so that I don't need to maintain it myself if it gets updated.
I have gone through other very similar questions, such as this and this that could not solve my issue. This answer gives me the feeling what I am trying to do is not trivial.
Is there any way to do this?
When you import a module for the first time, (as distinguished from importing a function), all code in that module executes. That means functions become defined, global variables become defined, etc. The reason we write an if __name__ == "__main__": block is so that when importing a module, that code does not execute (it will only execute if name == "main"). If you simply remove the if __name__ == "__main__": line and fix the indentation, that code will execute when you import the module. take this module hello.py for example:
def hello_world():
print("Hello world")
if __name__ == "__main__":
hello_world()
then if we import:
import hello
hello_world()
The code below will do the same thing as this case where the first module is again hello.py:
def hello_world():
print("hello world")
hello_world()
module to be executed:
import hello
I recommend you do not do it this way though, you really should just edit to include a main function.

Unable to Import Function Name

BASIC PROBLEM
I'm getting a name import error, but not in a way that is consistent between two files. I can import names from file A to file B, but not the other way around.
Update Based on Comments
I (stupidly) named the file "mix_max.py" instead of "min_max.py". I have changed the file accordingly and updated the GitHub repo. I have also updated the code in my question to reflect that.
CONTEXT AND CODE
Rather than reproduce all code here, I made a repo to show what I'm talking about.
I have the following min_max.py file:
https://github.com/jeffnyman/tic_tac_toe/blob/master/min_max.py
You can see a line in there to import from tic_tac_toe:
from tic_tac_toe import available_moves, apply_move, has_winner
That works just fine and I'm able to use those functions in min_max.py, such as on lines 74, 84, and 88.
However, I also have the following tic_tac_toe.py file:
https://github.com/jeffnyman/tic_tac_toe/blob/master/tic_tac_toe.py
You'll notice a line that does a similar import the other way around:
from min_max import min_max_player
PROBLEM
However when I try to use that (see line 126):
if __name__ == '__main__':
play_game(random_player, min_max_player, log=True)
This does not work. And it does not work because my from/import leads to "cannot import name min_max_player" when I try to run tic_tac_toe.py.
Workaround 1
I found I can fix this by changing my import to this:
import min_max
And then changing the code like this:
if __name__ == '__main__':
play_game(random_player, min_max.min_max_player, log=True)
The key change there being min_max.min_max_player.
What I don't see is why this is necessary, particularly since I didn't have to do this when importing from tic_tac_toe.py to min_max.py.
Workaround 2
I can apparently defer the import like this:
if __name__ == '__main__':
from min_max import min_max_player
play_game(random_player, min_max_player, log=True)
That works.
I'm coming to Python from a Ruby and Java context so I fear I'm missing something terribly obvious here. So maybe those things I list as "workarounds" are, in fact, the actual solution?
Based on the help of Stack and hurturk, who both pointed me in the right direction (see their comments), it looks like the concept I was missing and/or not seeing was the circular reference as well as perhaps the race condition therefrom.
So I believe one answer to my question are the workarounds that I posted in the original question.
Workaround 2 is to essentially to defer the import, as such:
if __name__ == '__main__':
from min_max import min_max_player
play_game(random_player, min_max_player, log=True)
I do find it perhaps odd that this doesn't lead to the same issue since the "defer" isn't really all that deferred; given that I handle this in the very first lines of tic_tac_toe.py that get executed.
I'm honestly not sure why either workaround is the answer necessarily, but they do have the benefit of working. It seems that it's just a matter of what kind of expression I have in place.
I like the Workaround 2 one because it allows me to use "min_max_player" similar to how I call "random_player". Workaround 1 forces me to use "random_player" and "min_max.min_max_player".

What is the best practice for linking python scripts

When linking scripts are there performance considerations when using os.system verses import? Next, when the imported script has imports that must be shared with the calling script is it okay to put those imports in the if __name__ == '__main__': block?
Short answer - no, not to a significant degree. Quite apart from the fact that PEP8 says use import and use it at the top of your file rather than at the start of the if __name__ == '__main__' block, there is no difference between using it at the head of your file versus under the if __name__ conditional.

Python user-defined exceptions placement and catching

I'm new to Python and I'm not sure what's the best place to put my user-defined exceptions, and where to catch them.
For example, I have a program which starts a game, when the game is stopped, an user-defined exception is raised (StopGame). I should catch this exception from outside the game since the game is throwing this exception. Though, the exception is specific to the game so the definition of the exception should be in the game module (or maybe the game package?).
Here is the simple layout of the program:
Program structure:
__main__.py
game/
__init__.py
game.py
__main__.py
import game
def main():
g = game.Game()
try:
g.start()
except game.StopGame:
print '\nbye bye!'
if __name__ == '__main__':
main()
game/__init__.py
from game import Game
from game import StopGame
game/game.py
class Game:
def start(self):
try:
a = raw_input('do you want to play?\n')
print 'cool'
except (KeyboardInterrupt, EOFError):
raise StopGame
if a == 'no':
raise StopGame
else:
print 'cool'
class StopGame(Exception):
pass
This code works fine like this, I'm just not sure this is the way to go. What I find somewhat disappointing is that I should import every exception in game/_init_.py using this setup. Otherwise I should catch the exception like:
except game.game.StopGame
Which looks a bit nasty. I think it's better to be able to reach all the attributes in the module 'game' from the variable 'game' in _main_.py. Then I know you can put this in game/_init_.py:
from game import *
Which will import all classes from game/game.py, but I heard that using * for importing is a bad practice.
So, my question is, what is the best way to do this? Maybe my whole setup is wrong, if so, I would like to hear what's the correct setup.
Thanks a lot in advance!
BTW: If you might wonder why I have a game module inside a game package: the idea is that the package will contain a lot of more modules that are related to the game, game/game.py is just the initiator of the whole game, maybe I should put that code into game/_init_.py?
How is it done elsewhere?
I think that the best way to answer your issue is to look at an actual Python package and see how it's built. I'll take the example of the excellent python-requests package.
This module is about making HTTP requests. Yours is about playing a game.
Basic HTTP requests functionality is imported in the requests/__init__.py file, but is defined elsewhere. That's what you're doing, but the 'elsewhere' could have a better name. Maybe game/core.py could be a good fit.
Exceptions are defined in the requests/exceptions.py file. It's usually appropriate for a relatively-small package to have all the exceptions in one place.
Note that the exceptions are imported into requests/__init__.py too! This makes them easier to import in other packages that might need to catch them!
Last, no from module import * is used. It's not going to take so much time to actually add exactly what's needed, so you should avoid *.
What can you do in your case?
Avoid having a game/game.py file, call it game/core.py or something
For a small package, put your exceptions in a game/exceptions.py file
In game/__init__.py, import what's usually needed from your package: the main classes and the exceptions.

Why use def main()? [duplicate]

This question already has answers here:
What does if __name__ == "__main__": do?
(45 answers)
Closed 3 years ago.
I've seen some code samples and tutorials that use
def main():
# my code here
if __name__ == "__main__":
main()
But why? Is there any reason not do define your functions at the top of the file, then just write code under it? ie
def my_function()
# my code here
def my_function_two()
# my code here
# some code
# call function
# print(something)
I just wonder if there is any rhyme to the main?
Without the main sentinel, the code would be executed even if the script were imported as a module.
Everyone else has already answered it, but I think I still have something else to add.
Reasons to have that if statement calling main() (in no particular order):
Other languages (like C and Java) have a main() function that is called when the program is executed. Using this if, we can make Python behave like them, which feels more familiar for many people.
Code will be cleaner, easier to read, and better organized. (yeah, I know this is subjective)
It will be possible to import that python code as a module without nasty side-effects.
This means it will be possible to run tests against that code.
This means we can import that code into an interactive python shell and test/debug/run it.
Variables inside def main are local, while those outside it are global. This may introduce a few bugs and unexpected behaviors.
But, you are not required to write a main() function and call it inside an if statement.
I myself usually start writing small throwaway scripts without any kind of function. If the script grows big enough, or if I feel putting all that code inside a function will benefit me, then I refactor the code and do it. This also happens when I write bash scripts.
Even if you put code inside the main function, you are not required to write it exactly like that. A neat variation could be:
import sys
def main(argv):
# My code here
pass
if __name__ == "__main__":
main(sys.argv)
This means you can call main() from other scripts (or interactive shell) passing custom parameters. This might be useful in unit tests, or when batch-processing. But remember that the code above will require parsing of argv, thus maybe it would be better to use a different call that pass parameters already parsed.
In an object-oriented application I've written, the code looked like this:
class MyApplication(something):
# My code here
if __name__ == "__main__":
app = MyApplication()
app.run()
So, feel free to write the code that better suits you. :)
if the content of foo.py
print __name__
if __name__ == '__main__':
print 'XXXX'
A file foo.py can be used in two ways.
imported in another file : import foo
In this case __name__ is foo, the code section does not get executed and does not print XXXX.
executed directly : python foo.py
When it is executed directly, __name__ is same as __main__ and the code in that section is executed and prints XXXX
One of the use of this functionality to write various kind of unit tests within the same module.
"What does if __name__==“__main__”: do?" has already been answered.
Having a main() function allows you to call its functionality if you import the module. The main (no pun intended) benefit of this (IMHO) is that you can unit test it.
Consider the second script. If you import it in another one, the instructions, as at "global level", will be executed.

Categories

Resources