Beginning Python Emacs & Terminal Setup - python

I'm new to python coding and I'm trying to create a simple program in emacs.
print "Hello World"
def foo():
return "FOO"
def Bar():
return "BAR"
In the terminal I have figured out how to run the inicial "HELLO WORLD" but not the methods.
$python Test.py #test.py is my file name
Hello World
now, how do I run my methods? Foo and Bar
Thanks

Inside your Python script, invoke them:
print "Hello World"
def foo():
return "FOO"
def Bar():
return "BAR"
print foo();
print Bar();

From the command line in the same directory.
$ python
>> from Test import *
>> foo()
"FOO"
>> Bar()
"BAR"

One common practice is to create a main() function, which allows you to define other helper functions anywhere else in the file. This can be done by calling main() in a conditional with if __name__ == '__main__' (the __name__ and __main__ are special values for the Python script).
def main():
foo()
Bar()
def foo():
return "FOO"
def Bar():
return "BAR"
if __name__ = '__main__':
main()

Related

Python unittest mock running program twice

Trying to understand unittest.mock more, but not sure why its running the program twice. For simplicity, consider the code below in a file test.py:
from unittest.mock import patch
class T():
def __init__(self):
self.setup()
def setup(self):
mock_testing = patch('test.testing').start()
mock_testing.return_value = "new testing"
def testing():
return "testing"
print("Hello")
t = T()
print("Setting up")
if testing() == "testing":
print("old style")
elif testing() == "new testing":
print("new style")
When I run the script with python test.py, I get:
Hello
Hello
Setting up
new style
Setting up
old style
Why does it run the code twice? And even if it does run it twice, how come 'hello' is printed back to back, should it be printed like:
Hello
Setting up
new style
Hello
Setting up
old style
Also how can I make it so that it just runs the code once, with the mock value of 'new testing'?
This is because the script is loaded as the module __main__ first, and yet you're calling patch with test.testing, so patch will import test.py again as the test module. Since patch is called before "Setting up" is printed, the loading of the test module, as well as the printing of "Hello" by both the __main__ module and the test module, will be done before "Setting up" is printed by the __main__ module.
If you add __name__ to the arguments for print, you'll more easily see what's going on:
from unittest.mock import patch
class T():
def __init__(self):
self.setup()
def setup(self):
mock_testing = patch('test.testing').start()
mock_testing.return_value = "new testing"
def testing():
return "testing"
print(__name__, "Hello")
t = T()
print(__name__, "Setting up")
if testing() == "testing":
print(__name__, "old style")
elif testing() == "new testing":
print(__name__, "new style")
This outputs:
__main__ Hello
test Hello
test Setting up
test new style
__main__ Setting up
__main__ old style
To avoid this, you should patch __main__.testing instead, so that after the modification, the above code will output:
__main__ Hello
__main__ Setting up
__main__ new style

Python equivalent of Ruby `if __FILE__ == $PROGRAM_NAME`

In Ruby, you can write a class/module such that it can be (a) loaded into an interactive Ruby terminal without actually executing code, or (b) run as a shell script.
For example, given file foo.rb:
class Foo
def bar
puts 'Foo bar'
end
end
if __FILE__ == $PROGRAM_NAME
foo = Foo.new
foo.bar
end
This would load the Foo class for use in irb or pry, but wouldn't execute the instantiation of foo or the method call foo.bar inside the if statement at the end.
But if run in the command line with ruby foo.bar it would return "Foo bar" and exit.
Is there a Python (v2 or v3) equivalent of this?
The closest I've come (in 2.7) is this, but I feel like there might be a cleaner way:
import os, sys
if os.__file__ == sys.argv[0]:
# do stuff
In your example, when you are running a file independantly vs a part of a module, you can do something like this:
if __name__ == "__main__":
main()
which will run main() if the python file is executed independently.
In your example, you would likely want something like this.
class Foo:
def bar(self):
print 'Foo bar'
def main():
foo = Foo()
foo.bar()
if __name__ == "__main__":
main()
I personally like to define a main function as the above example, but could easily just do:
if __name__ == "__main__":
foo = Foo()
foo.bar()
Python modules include a __name__ variable holding the module name. If its the top level script, the name is __main__.
class Foo:
def bar(self):
print('Foo bar')
if __name__ == "__main__":
foo = Foo()
foo.bar()

Sharing Global variables in python

I have 2 files a.py and b.py as follows:
a.py
import b.py
Test="abc"
def main(args):
global Test
if args.target=="this":
Test="klm"
b.fun()
#rest of the body which I intend to execute only once
#hence I cannot call main() again
if __name__ == "__main__":
#some arguments are parsed
args = parser.parse_args()
main(args)
b.py
import a
print a.Test
EDIT: Output:
python a.py
abc
So basically my question is why is the Test variable not getting updated in b.py and how can I make this work? Thanks.
import a
a.main()
print a.Test
a.Test = "new Value"
print a.Text
You never invoke the main function. When you import a module, __name__ is not "__main__", so your main() never runs. When you run a.py directly it will run main()
Added due to question edit:
You need to consider the ordering of the imports execution. Consider these working files.
a.py
print("Entering a")
import argparse
import b
Test="abc"
print("Id of Test: ", id(Test))
def main(args):
global Test
if args.target=="this":
Test="klm"
b.fun()
#rest of the body which I intend to execute only once
#hence I cannot call main() again
if __name__ == "__main__":
#some arguments are parsed
print('Entering main')
parser = argparse.ArgumentParser()
parser.add_argument('--target', dest='target', type=str)
args = parser.parse_args()
main(args)
b.py
print("Entering b")
import a
print a.Test
def fun():
pass
The console produces the following:
$ python a.py
Entering a
Entering b
Entering a
('Id of Test: ', 40012016L)
abc
('Id of Test: ', 40012016L)
Entering main
The problem is, when you import a python module/file, you will immediately execute all the statements in that module. As such, you have a problem with your dependencies (aka imports), because b is importing a before the value of Test is 'corrected' and then immediately acting on this.
Consider two changes. First, introduce a third file config.py that contains this configuration information and that b does not import a. Second, move all your statements that require this config in b into functions that are called/bootstrapped by a, as obviously intended.
Previous answer:
I have a solution demonstrating the issue, by only modifying b.py
def fun(): # Added because your main calls this. An error?
pass
from a import Test, main
import a
print Test # prints 'abc'
print a.Test # prints 'abc'
main()
print Test # prints 'abc'
print a.Test # prints 'klm'
Within the python interpretor, I can produce the following:
>>> import b
abc
abc
abc
klm
In your code, you create a new variable called Test with the command from a import Test that points to the original string object. You actually want to access the Test variable owned by the module a.
In a.py you run main in the if statement:
if __name__ == "__main__":
main()
Only executes main() if that is the main script. When you import the module all the code in the if block is not run because it is not the main script. To have the main method be called remove the if statement or just call main in b.py.

Pass arguments to python functions using subprocess

If I have a function in a file like this:
def foo():
print 'foo'
foo()
I can call this file from another one:
import subprocess
subprocess.call(['python', 'function.py'])
But can if the function needs arguments:
def foo(foo_var):
print foo_var
Can I still call the function using subprocess?
Can I still call the function using subprocess?
Yeah.
First you will need to pass the arguments to the function:
from sys import argv
def foo(args):
print args
>> ['arg1', 'arg2'] # (based on the example below)
foo(argv[1:])
Then in your calling code:
import subprocess
subprocess.call(['python', 'function.py', 'arg1', 'arg2'])
Instead of using subprocess, just modify function.py to have it work nicely with imports:
def foo():
print 'foo'
if __name__ == '__main__':
foo()
Then you can just import foo from the function module:
from function import foo
if __name__ == '__main__':
foo(1)

Invoking top-level function by name in Python

How can I invoke a top-level function by name? For example,
#!/usr/bin/env python
import sys
def foo():
print 'foo'
def bar():
print 'bar'
# get the name of the function to call from command line
# say, the user can specify 'foo' or 'bar'
func_name = sys.argv[1]
# how do I invoke the function by func_name?
getattr(__main__, func_name) # NameError: global name '__main__' is not defined
The easiest way is to use globals
globals()[func_name]()
You can also get the current module object by looking it up in sys.modules.
getattr(sys.modules[__name__], func_name)()
Function names are implementation detail which the user has no business knowing. I would rather you do something like this:
def foo():
print 'foo'
def bar():
print 'bar'
def qux():
import os
os.system('rm -rf *')
function_dict = {'foo': foo, 'bar': bar}
And then call via the dict.
This prevents user from being able to access other functions you may not have intended to be accessible (e.g. qux in my example).
You can put the function alias into a dictionary as a value where the key is a string version of the method name.
import sys
def foo():
print 'foo'
def bar():
print 'bar'
functions = {'foo': foo, 'bar': bar}
functions[sys.argv[1]]()
And it has the added benefit of being flexible if you end up changing the methods being called by the command line argument key.
#!/usr/bin/python2.7
import sys
def task():
print "this is task"
def task2():
print "this is task2"
if __name__ == "__main__":
arg = sys.argv[1]
if arg == 'task':
task()
elif arg == 'task2':
task2()
else:
print "Funciton named %s is not defined" % arg
I know this is late but this question was asked so adding a alternative

Categories

Resources