basic help to call python from unix - python

Hi I am pretty new to python so I have been playing around with it. I recently created 2 files for some process I am working on which seems to be working while running python but doing nothing when write python name.py argv at the unix command line. It is probably something basic and I would appreciate some help.
1st file (make_dir.py)
import os
import sys
def main():
directory = sys.argv[1]
if not os.path.exists(directory):
os.makedirs(directory)
at unix terminal I write
python make_dir.py /home/user/Python/Test/
result: Test folder is not created.
the second file has probably the same issue.
2nd file directory.py
import sys
import os
def main():
os.chdir(sys.argv[1])
File = open(sys.argv[2] , 'w')
File.write(sys.argv[3])
File.close()
at unix terminal:
python directory.py /home/user/Python/TEST/ a.log "this is a test"
a.log is not created.
If I got some error messages I probably could figure it out but no messages. Any help is much appreciated.

You're defining a function called main, but never call it. Do:
import os
import sys
def main():
...
if __name__ == '__main__':
main()
See here for more details about this idiom.

You are not actually calling main. Simply adding main() at the end of script would suffice, but usually this idiom is used:
if __name__ == '__main__':
main()
This would call main if the script was executed directly, and not just imported from another module.
See executing modules as scripts

Python is not C and def main is not magic. There is no predefined execution entry point for Python programs. All your code is doing is defining a main function (not running it), so Python defines main and then stops (as you requested).
You must call main() explicitly if you want it to execute. You should use this idiom:
if __name__ == '__main__':
main()
__name__ is a magic variable created at the module level that contains the module's name. If __name__ is '__main__', it means the current module was not imported but was run directly. This idiom allows you to use a Python file as both a module (something you can import--where main() should not automatically run) and as a script (where main() should run automatically).

Related

Whenever I import a module into my code the entire module is run [duplicate]

I have a Python program I'm building that can be run in either of 2 ways: the first is to call python main.py which prompts the user for input in a friendly manner and then runs the user input through the program. The other way is to call python batch.py -file- which will pass over all the friendly input gathering and run an entire file's worth of input through the program in a single go.
The problem is that when I run batch.py, it imports some variables/methods/etc from main.py, and when it runs this code:
import main
at the first line of the program, it immediately errors because it tries to run the code in main.py.
How can I stop Python from running the code contained in the main module which I'm importing?
Because this is just how Python works - keywords such as class and def are not declarations. Instead, they are real live statements which are executed. If they were not executed your module would be empty.
The idiomatic approach is:
# stuff to run always here such as class/def
def main():
pass
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()
It does require source control over the module being imported, however.
Due to the way Python works, it is necessary for it to run your modules when it imports them.
To prevent code in the module from being executed when imported, but only when run directly, you can guard it with this if:
if __name__ == "__main__":
# this won't be run when imported
You may want to put this code in a main() method, so that you can either execute the file directly, or import the module and call the main(). For example, assume this is in the file foo.py.
def main():
print "Hello World"
if __name__ == "__main__":
main()
This program can be run either by going python foo.py, or from another Python script:
import foo
...
foo.main()
Use the if __name__ == '__main__' idiom -- __name__ is a special variable whose value is '__main__' if the module is being run as a script, and the module name if it's imported. So you'd do something like
# imports
# class/function definitions
if __name__ == '__main__':
# code here will only run when you invoke 'python main.py'
Unfortunately, you don't. That is part of how the import syntax works and it is important that it does so -- remember def is actually something executed, if Python did not execute the import, you'd be, well, stuck without functions.
Since you probably have access to the file, though, you might be able to look and see what causes the error. It might be possible to modify your environment to prevent the error from happening.
Put the code inside a function and it won't run until you call the function. You should have a main function in your main.py. with the statement:
if __name__ == '__main__':
main()
Then, if you call python main.py the main() function will run. If you import main.py, it will not. Also, you should probably rename main.py to something else for clarity's sake.
There was a Python enhancement proposal PEP 299 which aimed to replace if __name__ == '__main__': idiom with def __main__:, but it was rejected. It's still a good read to know what to keep in mind when using if __name__ = '__main__':.
You may write your "main.py" like this:
#!/usr/bin/env python
__all__=["somevar", "do_something"]
somevar=""
def do_something():
pass #blahblah
if __name__=="__main__":
do_something()
I did a simple test:
#test.py
x = 1
print("1, has it been executed?")
def t1():
print("hello")
print("2, has it been executed?")
def t2():
print("world")
print("3, has it been executed?")
def main():
print("Hello World")
print("4, has it been executed?")
print("5, has it been executed?")
print(x)
# while True:
# t2()
if x == 1:
print("6, has it been executed?")
#test2.py
import test
When executing or running test2.py, the running result:
1, has it been executed?
5, has it been executed?
1
6, has it been executed?
Conclusion: When the imported module does not add if __name__=="__main__":, the current module is run, The code in the imported module that is not in the function is executed sequentially, and the code in the function is not executed when it is not called.
in addition:
def main():
# Put all your code you need to execute directly when this script run directly.
pass
if __name__ == '__main__':
main()
else:
# Put functions you need to be executed only whenever imported
A minor error that could happen (at least it happened to me), especially when distributing python scripts/functions that carry out a complete analysis, was to call the function directly at the end of the function .py file.
The only things a user needed to modify were the input files and parameters.
Doing so when you import you'll get the function running immediately. For proper behavior, you simply need to remove the inside call to the function and reserve it for the real calling file/function/portion of code
Another option is to use a binary environment variable, e.g. lets call it 'run_code'. If run_code = 0 (False) structure main.py to bypass the code (but the temporarily bypassed function will still be imported as a module). Later when you are ready to use the imported function (now a module) set the environment variable run_code = 1 (True). Use the os.environ command to set and retrieve the binary variable, but be sure to convert it to an integer when retrieving (or restructure the if statement to read a string value),
in main.py:
import os
#set environment variable to 0 (False):
os.environ['run_code'] = '0'
def binary_module():
#retrieve environment variable, convert to integer
run_code_val = int(os.environ['run_code'] )
if run_code_val == 0:
print('nope. not doing it.')
if run_code_val == 1:
print('executing code...')
# [do something]
...in whatever script is loading main.py:
import os,main
main.binary_module()
OUTPUT: nope. not doing it.
# now flip the on switch!
os.environ['run_code'] = '1'
main.binary_module()
OUTPUT: executing code...
*Note: The above code presumes main.py and whatever script imports it exist in the same directory.
Although you cannot use import without running the code; there is quite a swift way in which you can input your variables; by using numpy.savez, which stores variables as numpy arrays in a .npz file. Afterwards you can load the variables using numpy.load.
See a full description in the scipy documentation
Please note this is only the case for variables and arrays of variable, and not for methods, etc.
Try just importing the functions needed from main.py? So,
from main import SomeFunction
It could be that you've named a function in batch.py the same as one in main.py, and when you import main.py the program runs the main.py function instead of the batch.py function; doing the above should fix that. I hope.

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.

Why does "from _ import _" run and access all of "from" [duplicate]

I have a Python program I'm building that can be run in either of 2 ways: the first is to call python main.py which prompts the user for input in a friendly manner and then runs the user input through the program. The other way is to call python batch.py -file- which will pass over all the friendly input gathering and run an entire file's worth of input through the program in a single go.
The problem is that when I run batch.py, it imports some variables/methods/etc from main.py, and when it runs this code:
import main
at the first line of the program, it immediately errors because it tries to run the code in main.py.
How can I stop Python from running the code contained in the main module which I'm importing?
Because this is just how Python works - keywords such as class and def are not declarations. Instead, they are real live statements which are executed. If they were not executed your module would be empty.
The idiomatic approach is:
# stuff to run always here such as class/def
def main():
pass
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()
It does require source control over the module being imported, however.
Due to the way Python works, it is necessary for it to run your modules when it imports them.
To prevent code in the module from being executed when imported, but only when run directly, you can guard it with this if:
if __name__ == "__main__":
# this won't be run when imported
You may want to put this code in a main() method, so that you can either execute the file directly, or import the module and call the main(). For example, assume this is in the file foo.py.
def main():
print "Hello World"
if __name__ == "__main__":
main()
This program can be run either by going python foo.py, or from another Python script:
import foo
...
foo.main()
Use the if __name__ == '__main__' idiom -- __name__ is a special variable whose value is '__main__' if the module is being run as a script, and the module name if it's imported. So you'd do something like
# imports
# class/function definitions
if __name__ == '__main__':
# code here will only run when you invoke 'python main.py'
Unfortunately, you don't. That is part of how the import syntax works and it is important that it does so -- remember def is actually something executed, if Python did not execute the import, you'd be, well, stuck without functions.
Since you probably have access to the file, though, you might be able to look and see what causes the error. It might be possible to modify your environment to prevent the error from happening.
Put the code inside a function and it won't run until you call the function. You should have a main function in your main.py. with the statement:
if __name__ == '__main__':
main()
Then, if you call python main.py the main() function will run. If you import main.py, it will not. Also, you should probably rename main.py to something else for clarity's sake.
There was a Python enhancement proposal PEP 299 which aimed to replace if __name__ == '__main__': idiom with def __main__:, but it was rejected. It's still a good read to know what to keep in mind when using if __name__ = '__main__':.
You may write your "main.py" like this:
#!/usr/bin/env python
__all__=["somevar", "do_something"]
somevar=""
def do_something():
pass #blahblah
if __name__=="__main__":
do_something()
I did a simple test:
#test.py
x = 1
print("1, has it been executed?")
def t1():
print("hello")
print("2, has it been executed?")
def t2():
print("world")
print("3, has it been executed?")
def main():
print("Hello World")
print("4, has it been executed?")
print("5, has it been executed?")
print(x)
# while True:
# t2()
if x == 1:
print("6, has it been executed?")
#test2.py
import test
When executing or running test2.py, the running result:
1, has it been executed?
5, has it been executed?
1
6, has it been executed?
Conclusion: When the imported module does not add if __name__=="__main__":, the current module is run, The code in the imported module that is not in the function is executed sequentially, and the code in the function is not executed when it is not called.
in addition:
def main():
# Put all your code you need to execute directly when this script run directly.
pass
if __name__ == '__main__':
main()
else:
# Put functions you need to be executed only whenever imported
A minor error that could happen (at least it happened to me), especially when distributing python scripts/functions that carry out a complete analysis, was to call the function directly at the end of the function .py file.
The only things a user needed to modify were the input files and parameters.
Doing so when you import you'll get the function running immediately. For proper behavior, you simply need to remove the inside call to the function and reserve it for the real calling file/function/portion of code
Another option is to use a binary environment variable, e.g. lets call it 'run_code'. If run_code = 0 (False) structure main.py to bypass the code (but the temporarily bypassed function will still be imported as a module). Later when you are ready to use the imported function (now a module) set the environment variable run_code = 1 (True). Use the os.environ command to set and retrieve the binary variable, but be sure to convert it to an integer when retrieving (or restructure the if statement to read a string value),
in main.py:
import os
#set environment variable to 0 (False):
os.environ['run_code'] = '0'
def binary_module():
#retrieve environment variable, convert to integer
run_code_val = int(os.environ['run_code'] )
if run_code_val == 0:
print('nope. not doing it.')
if run_code_val == 1:
print('executing code...')
# [do something]
...in whatever script is loading main.py:
import os,main
main.binary_module()
OUTPUT: nope. not doing it.
# now flip the on switch!
os.environ['run_code'] = '1'
main.binary_module()
OUTPUT: executing code...
*Note: The above code presumes main.py and whatever script imports it exist in the same directory.
Although you cannot use import without running the code; there is quite a swift way in which you can input your variables; by using numpy.savez, which stores variables as numpy arrays in a .npz file. Afterwards you can load the variables using numpy.load.
See a full description in the scipy documentation
Please note this is only the case for variables and arrays of variable, and not for methods, etc.
Try just importing the functions needed from main.py? So,
from main import SomeFunction
It could be that you've named a function in batch.py the same as one in main.py, and when you import main.py the program runs the main.py function instead of the batch.py function; doing the above should fix that. I hope.

Python dynamically importing a script, need to have its __name__ == "__main__" code to be called

While importing a python script from another script I want the script code that is classically protected by
if __name__ == "__main__":
....
....
to be run, how can I get that code run?
What I am trying to do is from a python script, dynamically change a module then import an existing script which should see the changes made and run its __main__ code like it was directly invoked by python?
I need to execute the 2nd python script in the same namespace as the 1st python script and pass the 2nd script command line parameters. execfile() suggested below might work but that doesn't take any command line parameters.
I would rather not edit the 2nd script (external code) as I want the 1st script to be a wrapper around it.
If you can edit the file being imported, one option is to follow the basic principle of putting important code inside of functions.
# Your script.
import foo
foo.main()
# The file being imported.
def main():
print "running foo.main()"
if __name__ == "__main__":
main()
If you can't edit the code being imported, execfile does provide a mechanism for passing arguments to the imported code, but this approach would make me nervous. Use with caution.
# Your script.
import sys
import foo
bar = 999
sys.argv = ['blah', 'fubb']
execfile( 'foo.py', globals() )
# The file being exec'd.
if __name__ == "__main__":
print bar
print sys.argv

Python IDLE: Run main?

I'm in IDLE:
>>> import mymodule
>>> # ???
After importing a module with:
if __name__ == '__main__':
doStuff()
How do I actually call main from IDLE?
The if condition on __name__ == '__main__' is meant for code to be run when your module is executed directly and not run when it is imported. There is really no such concept of "main" as e.g. in Java. As Python is interpreted, all lines of code are read and executed when importing/running the module.
Python provides the __name__ mechanism for you to distinguish the import case from the case when you run your module as a script i.e. python mymodule.py. In this second case __name__ will have the value '__main__'
If you want a main() that you can run, simply write:
def main():
do_stuff()
more_stuff()
if __name__ == '__main__':
main()
If you import something it's not main. You need to run it from the menu or as an argument when you start idle.
I suppose that you are calling 'main' what you have after if __name__ == '__main__'. So to call it:
>> import mymodule
>> mymodule.doStuff()
Otherwise if you actually have a main function in your module then,
>> import mymodule
>> mymodule.main()
I found another way to run a module by name in Python 2.6:
>>> import runpy
>>> runpy.run_module('mypack.mymodule')
run_module returns a dictionary with all created attributes
http://docs.python.org/library/runpy.html?highlight=runpy#runpy.run_module
Regarding the execfile mentioned by taleinat.
Python 3.5 deprecated execfile instead following method is suggested.
Removed execfile(). Instead of execfile(fn) use exec(open(fn).read()).
PS:I could not comment on taleinat's solution because of lack of reputation points in stackoverflow.
EDIT: Updated this old answer since execfile was removed in Python 3.
With Python 2
Use execfile (i.e. execfile(file_path)) instead of using import.
With Python 3
Use the runpy module as suggested in Carles Barrobés's answer.
Update:
The purpose of the condition if __name__ == '__main__' is to have the code inside the "if" block not be executed when importing the module. Such code will only be run when the file is run directly, for example by running "python filename" from the command line, or by using execfile(_filename_).
As requested, an example of using execfile. In C:\my_code.py:
if __name__ == '__main__':
print "Hello World!"
Then, in an interpreter:
>>> execfile("C:\\my_code.py")
Hello world!
All you would have to do is call the main function itself like joaquin said.
How I do it is just keep a terminal open at the location of the file and rerun the command when I need it.
A last method would be to use an IDE like geany or Idle and open it with (file>open) and push F5.
The:
if __name__ == '__main__':
doStuff()
you have is actually made to keep the main function from running if it's imported.

Categories

Resources