Declaring CSV write globally - python

I have a script, but broken down it looks like this
import csv
#Global
writervariable = ''
def function1(): <--uses the writervariable.writerow
def function2():
def main():
writervariable = csv.writer(file)
function1()
function2()
main()
I am getting the error str has no writerow method, which make sense, but I thought setting it to csv.writer would change its type.
When I was just prototyping my script, I did this all in one big chaos function, and it worked.
Adding minimal reproducible example:
import csv
writer = ''
def function1():
writer.writerow(['data1', 'data2'])
def main():
with open('TestFile', 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['header1', 'header2'])
function1()
main()

You get the error because you actually have 2 writervariables in 2 different scopes. One is a string in the global scope, and another one - a csv.writer in the scope of the main() function.
When you try to call writervariable.writerow() inside the function1(), this function can "see" the writervariable in the global scope, which is a string, but the scope of the main function is out of visibility.
What you want to do is to pass the writervariable from the main() function to function1() and then use it there:
def function1(csv_writer): <--uses the writervariable.writerow
csv_writer.writerow()
def function2():
def main():
writervariable = csv.writer(file)
function1(writervariable)
function2()
main()

Related

Cache in python function not using global keyword

I am trying to create a cache array that my function can modify and access multiple times.
I can achieve this the ugly way:
def func():
global cache
try: cache
except NameError: cache = {"stuff"}
### does stuff with cache
...
but I can't do this with the nonlocal keyword, I would really like to know why...
UPDATE: user #quamrana asked for an example:
def main():
def func1():
global x
x = 3.14
def func2():
nonlocal y
y = 3.14
func1()
print(x)
func2()
print(y)
If __name__ == "__main__":
main()
I can also pass an outside variable to the function and use it with some methods, but I would like to avoid creating one manually:
def func(cache):
cache.update({"stuff": 42})
my_stuff = cache.get("stuff")
def main():
func_cache = {}
func(func_cache)
if __name__ == "__main__":
main()
are there good ways to do this kind of thing?

Using straing/data from another function

I'm trying to use returned data from one function into multiple other functions. But I don't want the first function to run each time; which is happening in my case.
#Function lab
def func_a():
print('running function a')
data = 'test'
return data
def func_b():
print(func_a())
def func_c():
print(func_a())
def func_d():
print(func_a())
if __name__ == '__main__':
func_a()
func_b()
func_c()
func_d()
Each time that whole function_a runs. But I just want the returned data from "func_a" in other functions.
IIUC, you could alleviate this with a simple class.
I hold the state of the class which runs func_a in a variable called output. I can then reference this output variable once the class has finished running as much as I like in all other functions without having to re-run func_a.
Hope this helps!
class FunctionA:
def __init__(self):
self.output = None
def run_function(self):
print('running function a')
data = 'test'
self.output = data
def func_b():
print(func_a.output)
def func_c():
print(func_a.output)
def func_d():
print(func_a.output)
if __name__ == '__main__':
func_a = FunctionA()
func_a.run_function()
func_b()
func_c()
func_d()
>>> running function a
>>> test
>>> test
>>> test
Your func_a does two things. To make this clear, let's call it, print_and_return_data.
There are several ways to to break apart the two things print_and_return_data does. One way is to split up the two behaviors into smaller sub-methods:
def print_and_return_data():
print('running function a') # keeping the old print behavior
data = 'test'
return data
into:
def print_run():
print('running function a') # keeping the old print behavior
def return_data():
return 'test'
def print_and_return_data():
print_run()
return return_data()
So that other functions only use what they need:
def func_b():
print(return_data())
Another way is to change print_and_return_data to behave differently the first time it's called from the following times it's called (I don't recommend this because functions changing based on how many times it's been called can be confusing):
context = {'has_printed_before': False}
def print_and_return_data():
if not context['has_printed_before']:
print('running function a')
context['has_printed_before'] = True
data = 'test'
return data
def func_b():
print(print_and_return_data())
if __name__ == '__main__':
func_a() # prints
func_b() # won't print
One way to avoid "functions behaving differently when they're called" is to pass the variation (the "context") in as an argument:
def return_data(also_print=False):
if also_print:
print('running function a')
data = 'test'
return data
def func_b():
print(return_data())
if __name__ == '__main__':
func_a(also_print=True) # prints
func_b() # won't print

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

Simple Python program with arguments not working

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()

Compiled without errors, but does not print anything

This gets compiled without any errors, but does not print anything.
def main():
test = readfile('text.txt')
print test
main()
def readfile(filename):
with open(filename) as f:
lines = f.readlines()
print lines
return lines
You should call main from outside itself. Otherwise it never gets called.
Basically it could look like this:
def main():
test = readfile('text.txt')
print test
def readfile(filename):
with open(filename) as f:
lines = f.readlines()
print lines
return lines
main()
There is nothing as an entry-point in python, like the main-function in C. A function called main is just another function. Your script will be executed from top to bottom.
Or without main:
with open(filename) as f: print(f.readlines())
main in python (on the end of the file):
def main():
print("main")
if __name__ == "__main__":
main()

Categories