I want to implement certain functionality using python that can be used in two ways:
as simple command line script, like python mylib.py
by importing into other python code
My first attempts look like this.
mylib.py:
from __future__ import print_function
import sys
class A(object):
def __init__(self, args):
print("my args: {}".format(args))
def main():
a = A(sys.argv)
print("got {}".format(a))
main()
Which I can directly invoke, or use elsewhere, like usage.py:
import mylib
mylib.A("bla")
That works, but it seems the import causes main() to be executed as well:
python scripts/using.py blub
my args: ['scripts/using.py', 'blub']
got <mylib.A object at 0x7ff17bc736d0>
my args: bla
Questions:
Is there a way to prevent main() from running when I go for python using.pl?
And beyond that:
Is this a good approach? Or are there well established best practices in python that I am violating here?
In other words: are there things I should do differently?
This is why you add
if __name__ == '__main__':
main()
If this .py file is directly invoked, your main will run. If your file is simply imported, it will not run main. See here
Since #CoryKramer has already answered the first part of the question, let me take a shot at the second part.
Code should exists where it belongs. If it has anything to do with parsing the script or the main execution, then it should be in the script. Any other piece of code shouldn't be the part of script file.
Generally, in production code, you should never import from a script file. The common code should exist in it's own class in a separate file or just in a separate file in case of procedural approach. This way the code in your script would be succinct and the code in the common file is reusable in other production code and you won't run a risk of accidentally executing a script, just to use the common code.
# common.py
class A(object):
def __init__(self, args):
print("my args: {}".format(args))
# mylib.py
from common import A
if __name__ == '__main__':
a = A(sys.argv)
print("got {}".format(a))
Related
I have a python library/package that contains modules with functions & classes I usually import inside of my application's main script. However, these modules each contain their own 'main()' function so that I can run them individually if needed. Here's an example:
# my_module.py
import logging
log = logging.getLogger(__name__)
class SomeModuleClass:
def __init__(self):
pass
def some_module_function():
pass
def main():
# Some code when running the module as the main script
if __name__ == "__main__":
main()
I have two questions related to running this module as the main script (i.e. running python my_module.py):
What's the cleanest way to use the logging module in this case? I usually simply overwrite the global 'log' variable by including the following in the main() function, but I'm not sure if there's a more pythonic way of doing this:
def main():
# ... some logging setup
logging.config.dictConfig(log_cfg_dictionary)
global log
log = logging.getLogger(__name__)
Is it considered good practice to include import statements inside of the main() function for all libraries only needed when running the script as main? For instance, one might need to use argparse, json, logging.config, etc. inside of the main function, but these libraries are not used anywhere else in my module. I know the most pythonic way is probably to keep all the import statements at the top of the file (especially if there's no significant difference in terms of memory usage or performance), but keeping main function-specific imports inside of main() remains readable & looks cleaner in my opinion.
I have two python files. One is main.py which I execute. The other is test.py, from which I import a class in main.py.
Here is the sample code for main.py:
from test import Test
if __name__ == '__main__':
print("You're inside main.py")
test_object = Test()
And, here is the sample code for test.py:
class Test:
def __init__(self):
print("you're initializing the class.")
if __name__ == '__main__':
print('You executed test.py')
else:
print('You executed main.py')
Finally, here's the output, when you execute main.py:
You executed main.py
You're inside main.py
you're initializing the class.
From the order of outputs above, you can see that once you import a piece of a file, the whole file gets executed immediately. I am wondering why? what's the logic behind that?
I am coming from java language, where all files included a single class with the same name. I am just confused that why python behaves this way.
Any explanation would be appricated.
What is happening?
When you import the test-module, the interpreter runs through it, executing line by line. Since the if __name__ == '__main__' evaluates as false, it executes the else-clause. After this it continues beyond the from test import Test in main.py.
Why does python execute the imported file?
Python is an interpreted language. Being interpreted means that the program being read and evaluated one line at the time. Going through the imported module, the interpreter needs to evaluate each line, as it has no way to discern which lines are useful to the module or not. For instance, a module could have variables that need to be initialized.
Python is designed to support multiple paradigms. This behavior is used in some of the paradigms python supports, such as procedural programming.
Execution allows the designer of that module to account for different use cases. The module could be imported or run as a script. To accommodate this, some functions, classes or methods may need to be redefined. As an example, a script could output non-critical errors to the terminal, while an imported module to a log-file.
Why specify what to import?
Lets say you are importing two modules, both with a Test-class. If everything from those modules is imported, only one version of the Test-class can exist in our program. We can resolve this issue using different syntax.
import package1
import package2
package1.Test()
packade2.Test()
Alternatively, you can rename them with the as-keyword.
from package1 import Test
from package2 import Test as OtherTest
Test()
OtherTest()
Dumping everything into the global namepace (i.e from test import *) pollutes the namespace of your program with a lot of definitions you might not need and unintentionally overwrite/use.
where all files included a single class with the same name
There is not such requirement imposed in python, you can put multiple classes, functions, values in single .py file for example
class OneClass:
pass
class AnotherClass:
pass
def add(x,y):
return x+y
def diff(x,y):
return x-y
pi = 22/7
is legal python file.
According to interview with python's creator modules mechanism in python was influenced by Modula-2 and Modula-3 languages. So maybe right question is why creators of said languages elected to implement modules that way?
I have a flask application, and I have split the code into multiple python files, each dedicated to a specific portion of the overall program (db, login, admin, etc). Most of the files have some sort of setup code that creates their respective module's object, which must have access to the Flask object defined in my main file. Some of the modules also need access to variables in other modules, but when importing them, they are run again, even though they were imported in main already.
The following code is an example of the problem.
If I have a main.py like this
import foo
import bar
if __name__ == "__main__":
foo.foofunc()
foo.py
import bar
#bar.barable
def foo(string):
print(string)
and bar.py
import foo
foo.foo("hello")
def barable(fun):
def r(*args, **kwargs):
print("this function is completely unbarable")
func(*args, **kwargs)
This code doesn't work because foo imports bar, which imports foo, which runs bar.barable, which hasn't been defined yet.
In this situation (assuming that calling foo.foo is necessary), is my only option to extract bar.barable out of bar and into a seperate module, or is there some other way to fix this?
I know that importing a module in python runs the file, but is there some way to put some of the code into the same sort of check as __name__ == "__main__" but to check if it is being imported by main and not by another module?
I defined a class called Prof in a script called AddPntCode90_27.py. It opens some files, does some math, creates output files and so. Now I want to re-use the class for another programme. But as AddPntCode90_27.py is not a module it always executes the script instead of just importing the class.
I did from AddPntCode90_27 import * as well as from AddPntCode90_27 import Prof.
I am familiar with this article. So my questions are:
is it bad practice to define a class within a script like this? Should I always keep them in a separated file?
is there, however, a way to import just the class and its methods without executing the script it is defined in?
Ah, I'm running Python 2.7.
The way to do what you want is to use an if __name__ == "__main__" block. See this question.
It's perfectly fine to define classes in scripts, but you cannot import the class without executing the script, because it is only by executing the script that you define the class. Class definitions are not a "compile-time declaration" in Python; they are executed in order just like everything else in the module. You should use an if __name__=="__main__" block to protect code that you don't want to be run when you import your file as a module.
You should the if __name__="__main__: idiom to check whether Python is running the code or the code is being imported as a module.
I have a module that has the usual
if __name__ == '__main__':
do stuff...
idiom.
I'd like to import that from another module, and fool it into running that code. Is there any way of doing this?
I should mention, for reasons I won't go into here, I'm not in a position to change the code in the imported module. I need to somehow modify the import procedure so that it's name is main when imported, perhaps using ihooks or similar.
As pointed out in the other answers, this is a bad idea, and you should solve the issue some other way.
Regardless, the way Python does it is like this:
import runpy
result = runpy._run_module_as_main("your.module.name"))
There is, execute the script instead of importing it. But I consider this an extremely hackish solution.
However the ideal pattern would be:
def do_stuff():
... stuff happens ...
if __name__ == '__main__':
do_stuff()
that way you can do:
from mymodule import do_stuff
do_stuff()
EDIT: Answer after clarification on not being able to edit the module code.
I would never recommend this in any production code, this is a "use at own risk" solution.
import mymodule
with open(os.path.splitext(mymodule.__file__)[0] + ".py") as fh:
exec fh.read()
Put that code in a function, and call it from the module you are importing it into as well.
def stuff():
...
if __name__ == '__main__':
stuff()
And then in the module you are importing it into:
import module
module.stuff()
The correct answer has been already given however it is confined in a comments (see How to import a module as __main__?
and How to import a module as __main__?).
The same with proper formatting:
import runpy
runpy.run_module("your.module.name", {}, "__main__")
or
import runpy
runpy.run_path("path/to/my/file.py", {}, "__main__")
Code in a main stanza usually never makes sense to run directly. If you want to run it then use subprocess to run it in another Python interpreter.
Here is an example of a main module in Python:
#! /usr/bin/env python
import sys
import os
def main(arg1, arg2, arg3):
print(arg1, arg2, arg3)
if __name__ == "__main__":
main(*sys.argv)
But you can also include
def main():
#The module contains Python code specific to the library module,
#like tests, and follow the module with this:
if __name__ == "__main__":
main(*sys.argv)
in any module you would like to run as main.
For example, if you have a library module, you can always use this construct to execute something specific like tests.
Put it in a function:
def _main():
do stuff
if __name__ == '__main__':
main()