Simple Python program with arguments not working - python

Just learning Python and spent quite some time on this. Why isn't it outputting anything when I pass arguments like this:
python new2.py Alice
Source code:
#!/usr/bin/python
import sys
def Hello(name):
if name == 'Alice' or name == 'Nick':
name = name + '!!!'
else:
name = name + '???'
print 'Hello', name
def main():
Hello(sys.argv[1])

Python doesn't implicitly call your main function. You either call it directly:
def main():
Hello(sys.argv[1])
main()
or you wrap it in an idiomatic clause to do a similar thing:
if __name__ == "__main__":
main()

Related

using variables of main file in imported file

I am using python and cannot solve the problem myself. I defined the variables(rb. data) in the 'main file' below. And I imported 'hp file' to use hotplate function. ( i611Robot, Teachdata, MotionParam,Position are included in 'A file' )
from hp import *
from A import *
def main():
rb = i611Robot()
data = Teachdata()
m1 = MotionParam(30,20,10,2,2)
position_1 = Position(100,200,100,0,0,0)
...
....
hotplate(rb)
if __name__ == '__main__':
main()
And this is the 'hp file' which is imported.
from A import *
def hotplate(rb) :
rb.motionparam( m1 )
rb.move( position_1 )
.......
But the problem is when I play 'main file', it says
File "main.py" line.., in <module>
main()
File "main/py", line ...., in main
hotplate()
File ".../hotplate.py", in line .., in hotplate
rb.motionparam( m1 )
NameError : global name 'm1' is not defined
I already asked question about how to use rb in hotplate.py and get answer that I have to put rb in hotplate(). This works well.
But another problem is that there are so many variables, parameters like rb and m1,
position_1 that will be used in hotplate.py file.
How can I use those all variables,instances,parameters in hotplate.py file.
As #Barmar already commented, functions should get their information from parameters.
Your code
What you're doing doesn't work:
def a():
myVar = "Hello"
b()
def b():
print(myVar)
if __name__ == "__main__":
a()
The function b doesn't know the variable myVar, the variable is out of scope.
Solution
What you have to do is to pass the arguments which the function needs to the function's parameters:
def a():
myVar = "Hello"
b(myVar)
def b(myArg):
print(myArg)
if __name__ == "__main__":
a()
Output
Hello
Learn about python functions here: https://www.w3schools.com/python/python_functions.asp

Access variable in main function from other script

this is probably a silly question but I'm a little bit struggling to make it work :
Let's say I have two files :
script1.py :
myValue = 0
def addition():
global myValue
myValue += 1
if __name__ == '__main__':
addition()
print(myValue)
script2.py :
def getMyValue():
from script1 import myValue
print(myValue)
getMyValue()
Output : 0
I want my 2nd script to access the updated value so I can get '1' as output.
How do you think I can do it properly ?
Thanks for your replies
The variable myValue is not updated in script2.py as you don't call the addition() function by importing script1. That is due to the condition
if __name__ == '__main__' which ensures that every following logic is only executed if you run the script itself. If you import script1 into another script the condition if __name__ == '__main__' becomes False and none of the below code will run.
You could either just call addition() directly in script1, which would not be a very clean solution -
script1:
myValue = 0
def addition():
global myValue
myValue += 1
addition()
or reconsider if addition() actually needs to operate on a global variable. Be aware that globals in python are just global within a module and not across several modules, so importing both the variable and the function into script 2 would not allow you to call addition() in script2 with the expected effects. However, i would suggest making it accept a parameter like this - script1:
myValue = 0
def addition(a_value):
a_value += 1
return a_value
if __name__ == '__main__':
myValue = addition(myValue)
print(myValue)
and then call the addition function in script2, for example as follows - script2:
from script1 import *
def getMyValue():
my_new_value = addition(myValue)
print(my_new_value)
getMyValue()

Why can't multiprocess.Process call getattr method?

Trying to call two methods say_hello and say_world by getattr() in multiprocessing.Process, but method say_world hasn't been executed. How can I make it possible? Thanks.
# -*- coding: utf-8 -*-
from multiprocessing import Process
import time
class Hello:
def say_hello(self):
print('Hello')
def say_world(self):
print('World')
class MultiprocessingTest:
def say_process(self, say_type):
h = Hello()
while True:
if hasattr(h, say_type):
result = getattr(h, say_type)()
print(result)
time.sleep(1)
def report(self):
Process(target=self.say_process('say_hello')).start()
Process(target=self.say_process('say_world')).start() # This line hasn't been executed.
if __name__ == '__main__':
t = MultiprocessingTest()
t.report()
The parameter target expects a reference to a function as value but your code passes None to it. These are the necessary parts to change:
class Hello:
def say_hello(self):
while True:
print('Hello')
time.sleep(1)
def say_world(self):
while True:
print('World')
time.sleep(1)
class MultiprocessingTest:
def say_process(self, say_type):
h = Hello()
if hasattr(h, say_type):
return getattr(h, say_type) # Return function reference instead of execute function
else:
return None

Import module containing input/output

I have a python module file (func.py) and a unit test file (f_test.py):
# func.py
def f(x):
return x + 1
x = input("Enter x: "))
print("f(x): " + str(f(x)))
and
# f_test.py
import unittest
from func import f
class MyTest(unittest.TestCase):
def test(self):
self.assertEqual(f(1), 2)
When I run f_test.py I expect the test suite to be executed (successfully).
Instead however I see the following input:
Finding files... done.
Importing test modules ... Enter x:
If I comment out the input/output lines from func.py then I get the expected behaviour.
How do I achieve it without modifying func.py?
When you import func, all the code inside is run. Running the definition def f(x)... is what creates the function f.
You can distinguish between importing and running a file by using if __name__=='__main__'.
For instance:
# func.py
def f(x):
return x + 1
if __name__ == '__main__':
x = input("Enter x: "))
print("f(x): " + str(f(x)))
When you run func.py, __name__=='__main__' will be true. When you import it, it will be false (__name__ will be 'func' instead).
Of course, the correct answer is to modify func.py. If you absolutely, positively, won't modify func.py, then you could redirect standard input:
# f_test.py
import os
import sys
import unittest
oldstdin, sys.stdin = sys.stdin, StringIO.StringIO('7')
try:
from func import f
finally:
sys.stdin = oldstdin
class MyTest(unittest.TestCase):
def test(self):
self.assertEqual(f(1), 2)
You need to add to the bottom of f_test.py:
if __name__ == '__main__':
unittest.main()
This way the tests will be executed when the file is run (I forget this more times than I would like to admit).

Python Unit Testing checking stdout of a list after while loop

I tried to word the question right, but what I'm trying to do is check the stdout of a list after the while statement. I mock the user input for two iterations and break during the thirs iteration.
here is my run code.
def main():
pirateList = []
maxLengthList = 6
while len(pirateList) < maxLengthList:
item = input("Argh! Enter the item: ")
if item == "exit":
break;
else:
pirateList.append(item)
print(pirateList)
print(pirateList)
main()
here is my test code, i should be expecting [bow, arrow]
import unittest
from unittest.mock import patch
import io
import sys
from RunFile import main
class GetInputTest(unittest.TestCase):
#patch('builtins.input', side_effect=["bow", "arrow","exit"])
def test_output(self,m):
saved_stdout = sys.stdout
try:
out = io.StringIO()
sys.stdout = out
main()
output = out.getvalue().strip()
assert output.endswith('[bow, arrow]')
finally:
sys.stdout = saved_stdout
if __name__ == "__main__":
unittest.main()
when I run this code the program just gets hung up.No errors or tracks
The import statement you are having
from RunFile import main
Actually runs the main function, as it should, and asks for the input. You should have the standard if-clause there:
if __name__ == "__main__":
main()
You might also want to change the stdout handling, here is an example:
class GetInputTest(unittest.TestCase):
#patch('builtins.input', side_effect=["bow", "arrow","exit"])
#patch('sys.stdout', new_callable=StringIO)
def run_test_with_stdout_capture(self , mock_output, mock_input ):
main()
return mock_output.getvalue()
def test( self ):
print ("GOT: + " + self.run_test_with_stdout_capture())
if __name__ == "__main__":
unittest.main()
Do note that you cannot print inside the #patch sys.stdout -- it will get captured!

Categories