calling python script from another fails at class definition - python

I have a script called insertPrintCode.py, which works on its own.
I want to call this from another python script using
def main():
execfile("insertPrintCode.py")
def execfile(filename):
exec(compile(open(filename).read(), filename, 'exec'))
This fails inside insertPrintCode.py at the first use of
newSearch = FileSearch()
with
NameError: global name 'FileSearch' is not defined
FileSearch is a class defined inside the same file.

Related

Importing variable from called script repeats the entire calling script

I have a main.py file
import common_functions as conf
print("Main File:")
filename = conf.testing()
from TC import TC
and I want to assign the below return statement as a variable "filename"
common_functions.py
def testing():
print("This should only print once!")
return "awesome file"
I want to then be able to access this variable, in another file that I am importing (TC )
TC.py
from main import filename
print("TC File:")
print(f"Filename is: {filename}")
however, currently, if I do this, then the output is:
Main File:
This should only print once!
Main File:
This should only print once!
TC File:
Filename is: awesome file
I am really struggling with this one, as I am trying to pass a variable into the called scripts, but that variable is only named from another function... so it seems as though everytime I it's called, then the function kicks off again
I would like to be able to set the variable filename in the main file from the function it is calling, and then in the called file (TC.py) I would like to be able to access that variable as a string, not rerun everything.
Is that possible?

Creation of a class instance by reflection in Python does not work

I have the following code:
theModule = locate(<the location of my python script in the file system>)
class_ = getattr(theModule, '<the class of my module>')
myAppli = class_()
But I always have an AttributeError exception when trying to perform the "getattr" method.
My objective was to create a Python class from a file somewhere in the file system, and execute methods on it by reflection without using the class declaration in the Python code.
Example
For example, I have the following python script, let's say that the name of the script file is: myScript.py
import sys
class PythonAppli:
def aMethod(self):
sys.echo('I am here\n')
And I perform this in another script in the same directory:
from pydoc import locate
theModule = locate('myScript.py')
class_ = getattr(theModule, 'pythonAppli')
myAppli = class_()
I have the following exception on the "getattr" line:
AttributeError: class PythonAppli has no attribute 'pythonAppli'
Note that if I add this line before my "getattr" method call:
inspect.getmembers(theModule)
I find 'pythonAppli' in the list of attributes.
I looked on the question about dynamic instanciation on StackOverflow but could not find my error here.
Per MisterMiyagi answer, my mistake was theModule was already my desired class. The following code did work:
from pydoc import locate
theModule = locate('myScript.py')
pythonAppli = theModule()
So it was much more simple that I imagined.

Calling exec, getting NameError though the name is defined

I have a file named file.py containing the following script:
def b():
print("b")
def proc():
print("this is main")
b()
proc()
And I have another file named caller.py, which contains this script:
text = open('file.py').read()
exec(text)
When I run it, I get the expected output:
this is main
b
However, if I change caller.py to this:
def main():
text = open('file.py').read()
exec(text)
main()
I get the following error:
this is main
Traceback (most recent call last):
File "./caller.py", line 7, in <module>
main()
File "./caller.py", line 5, in main
exec(text)
File "<string>", line 10, in <module>
File "<string>", line 8, in main
NameError: global name 'b' is not defined
How is function b() getting lost? It looks to me like I'm not violating any scope rules. I need to make something similar to the second version of caller.py work.
exec(text) executes text in the current scope, but modifying that scope (as def b does via the implied assignment) is undefined.
The fix is simple:
def main():
text = open('file.py').read()
exec(text, {})
This causes text to run in an empty global scope (augmented with the default __builtins object), the same way as in a regular Python file.
For details, see the exec documentation. It also warns that modifying the default local scope (which is implied when not specifying any arguments besides text) is unsound:
The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.
Would it work for you if you imported and called the function instead?
myfile.py
def b():
print("b")
def proc():
print("this is main")
b()
caller.py
import myfile
myfile.proc()

Python: Calling functions from the same module

I am designing a module, say mymodule.py and I write the code for the module as follows:
def charCount(my_string, my_char):
a = my_string.count(my_char)
return a
def aCount(my_string):
a = charCount(my_string, 'a')
return a
Inside Python shell, I use the following command:
import mymodule as mm
and then,
mString = 'ghghghghgaaaaa'
and then
a = mm.aCount(mString)
It is seen that there is an error. Apparently, the function is not able to be called from the same module. How can this be avoided?
You need to put return statement in both the functions and it would work fine.
Try this:
def charCount(my_string, my_char):
a = my_string.count(my_char)
return a
def aCount(my_string):
a = charCount(my_string, 'a')
return a

Python Help: Accessing static member variable from another class

I'll do my best to describe the issue I am having. I am building a Python program that is built on multiple classes and uses the unittest framework. In a nutshell, the Main.py file has a "ValidateDriver" class that defines a "driver" variable as an ElementTree type. If I point this directly to the XML file I need to parse, (i.e. driver = ElementTree.parse(rC:\test.xml)) then I can access it from another class. However, in reality I don't have the actual XML file that is passed in from the command-line until you get to the Main function in the ValidateDriver class. So under the ValidateDriver class driver would really be driver = ElementTree and then in the main function I would reassign that variable to ValidateDriver.driver = ElementTree.parse(args.driver). However, this is the crux. When I go to the other class and try to call ValidateDriver.driver I don't have the "findall" method/attribute available. Again, the only way it will work is to do something like: ElementTree.parse(rC:\test.xml)). If I did this in C# it would work, but I am new to Python and this is kicking my butt. Any help/suggestions is appreciated. I've included the code for both classes.
Main Function:
import sys
import argparse
import xml.etree.ElementTree as ElementTree
import unittest
import Tests.TestManufacturer
class ValidateDriver:
driver = ElementTree
def main(argv):
parser = argparse.ArgumentParser(description='Validation.')
parser.add_argument('-d', '--driver', help='Path and file name xml file', required=True)
parser.add_argument('-v', '--verbosity',
help='Verbosity for test output. 1 for terse, 2 for verbose. Default is verbose',
default=2, type=int)
#args = parser.parse_args()
args = r'C:\test.c4i'
#print ("Validate Driver: %s" % args.driver)
#print ("Verbosity Level: %s" % args.verbosity)
ValidateDriver.driver = ElementTree.parse(r'C:\test.c4i')
loader = unittest.TestLoader()
suite = loader.loadTestsFromModule(Tests.TestManufacturer)
runner = unittest.TextTestRunner(verbosity=2) # TODO Remove this...
# TODO Uncomment this...
runner = unittest.TextTestRunner(verbosity=args.verbosity)
result = runner.run(suite)
if __name__ == "__main__":
main(sys.argv[1:])
Other Class, Test Manufacturer:
import unittest
import Main
manufacturer = ['']
class Tests(unittest.TestCase):
# Test to see if Manufacturer exists.
def test_manufacturer_exists(self):
for m in Main.ValidateDriver.driver.findall('./manufacturer'):
print m.text
Producing the following error:
C:\Python27\python.exe C:\Users\test\PycharmProjects\Validator\Main.py
Traceback (most recent call last):
File "C:\Users\test\PycharmProjects\Validator\Main.py", line 22, in <module>
class ValidateDriver:
File "C:\Users\test\PycharmProjects\Validator\Main.py", line 65, in ValidateDriver
main(sys.argv[1:])
File "C:\Users\test\PycharmProjects\Validator\Main.py", line 36, in main
ValidateDriver.driver = ElementTree.parse(r'C:\test.c4i')
NameError: global name 'ValidateDriver' is not defined
Process finished with exit code 1
The main problem seems to be that your main script is wrapped in a class. There's really no reason for this, and is quite confusing.
if __name__ == "__main__":
main_object = ValidateDriver()
main_object.main(sys.argv[1:])
This should go outside the class definition
This has nothing to do with "findall" being available. The issue is that the class itself hasn't yet been completely declared at the time you try to access it. In python, the file is read top to bottom. For example, this is not allowed:
if __name__ == "__main__":
f()
def f():
...
The call to f must happen at the bottom of the file after it is declared.
What you're doing with ValidateDriver is similar, because the class isn't defined until the statements directly in its body are executed (this is different from functions, whose bodies of course aren't executed until they are called). You call main(sys.argv[1:]) inside the class body, which in turn tries to access ValidateDriver.driver, which doesn't exist yet.
Preferably, the main function, as well as the code which calls it, should be outside the class. As far as I can tell, the class doesn't need to exist at all (this isn't C# or Java -- you can put code directly at the module level without a class container). If you insist on putting it in a class as a static method, it must be defined as a class method:
#classmethod
def main(cls, argv):
...
which can then be called (outside the class definition) like:
ValidateDriver.main(sys.argv[1:])
But I stress that this is non-standard and should not be necessary.

Categories

Resources