Import class without executing .py it is in? - python

I defined a class called Prof in a script called AddPntCode90_27.py. It opens some files, does some math, creates output files and so. Now I want to re-use the class for another programme. But as AddPntCode90_27.py is not a module it always executes the script instead of just importing the class.
I did from AddPntCode90_27 import * as well as from AddPntCode90_27 import Prof.
I am familiar with this article. So my questions are:
is it bad practice to define a class within a script like this? Should I always keep them in a separated file?
is there, however, a way to import just the class and its methods without executing the script it is defined in?
Ah, I'm running Python 2.7.

The way to do what you want is to use an if __name__ == "__main__" block. See this question.
It's perfectly fine to define classes in scripts, but you cannot import the class without executing the script, because it is only by executing the script that you define the class. Class definitions are not a "compile-time declaration" in Python; they are executed in order just like everything else in the module. You should use an if __name__=="__main__" block to protect code that you don't want to be run when you import your file as a module.

You should the if __name__="__main__: idiom to check whether Python is running the code or the code is being imported as a module.

Related

Why do you run other lines of codes of a python file(say test.py) when you are just importing a piece of test.py from somewhere else (say main.py)?

I have two python files. One is main.py which I execute. The other is test.py, from which I import a class in main.py.
Here is the sample code for main.py:
from test import Test
if __name__ == '__main__':
print("You're inside main.py")
test_object = Test()
And, here is the sample code for test.py:
class Test:
def __init__(self):
print("you're initializing the class.")
if __name__ == '__main__':
print('You executed test.py')
else:
print('You executed main.py')
Finally, here's the output, when you execute main.py:
You executed main.py
You're inside main.py
you're initializing the class.
From the order of outputs above, you can see that once you import a piece of a file, the whole file gets executed immediately. I am wondering why? what's the logic behind that?
I am coming from java language, where all files included a single class with the same name. I am just confused that why python behaves this way.
Any explanation would be appricated.
What is happening?
When you import the test-module, the interpreter runs through it, executing line by line. Since the if __name__ == '__main__' evaluates as false, it executes the else-clause. After this it continues beyond the from test import Test in main.py.
Why does python execute the imported file?
Python is an interpreted language. Being interpreted means that the program being read and evaluated one line at the time. Going through the imported module, the interpreter needs to evaluate each line, as it has no way to discern which lines are useful to the module or not. For instance, a module could have variables that need to be initialized.
Python is designed to support multiple paradigms. This behavior is used in some of the paradigms python supports, such as procedural programming.
Execution allows the designer of that module to account for different use cases. The module could be imported or run as a script. To accommodate this, some functions, classes or methods may need to be redefined. As an example, a script could output non-critical errors to the terminal, while an imported module to a log-file.
Why specify what to import?
Lets say you are importing two modules, both with a Test-class. If everything from those modules is imported, only one version of the Test-class can exist in our program. We can resolve this issue using different syntax.
import package1
import package2
package1.Test()
packade2.Test()
Alternatively, you can rename them with the as-keyword.
from package1 import Test
from package2 import Test as OtherTest
Test()
OtherTest()
Dumping everything into the global namepace (i.e from test import *) pollutes the namespace of your program with a lot of definitions you might not need and unintentionally overwrite/use.
where all files included a single class with the same name
There is not such requirement imposed in python, you can put multiple classes, functions, values in single .py file for example
class OneClass:
pass
class AnotherClass:
pass
def add(x,y):
return x+y
def diff(x,y):
return x-y
pi = 22/7
is legal python file.
According to interview with python's creator modules mechanism in python was influenced by Modula-2 and Modula-3 languages. So maybe right question is why creators of said languages elected to implement modules that way?

Add a module when running a python program from terminal

I wrote a module that, if it is imported, automatically changes the error output of my program. It is quite handy to have it in almost any python code I write.
Thus I don't want to add the line import my_errorhook to every code I write but want to have this line added automatically.
I found this answer, stating that it should be avoided to change the behavior of python directly. So I thought about changing the command line, something like
python --importModule my_errorhook main.py
and defining an alias in the bashrc to overwrite the python command to automatically add the parameter. Is there any way I could achieve such a behavior?
There is no such thing like --importModule in python command line. The only way you can incept the code without explicitly importing is by putting your functions in builtins module. However, this is a practice that is discouraged because it makes your code hard to maintain without proper design.
Let's assume that your python file main.py is the entry point of the whole program. Now you can create another file bootstrap.py, and put below codes into the new file.
import main
__builtins__.func = lambda x: x>=0
main.main()
Then the function func() can be called from all modules without being imported. For example in main.py
def main():
...
print(func(1))
...

How to run a particular python script present in any other directory after a "if" statement in a python script?

I need to know how to run a python script from a python script present in other directory like the following algorithm:
if option==true
run /path/to/the/directory/PYTHON SCRIPT
else
ch3ka points out that you can use exec to do this. There are other ways like subprocess or os.system as well.
But Python works well with itself by design - this is the entire concept behind creating and importing modules. I think for most cases you'd be better off just encapsulating the script in a class, and moving the code that was previously in the if __name__ == '__main__' section of the script into the __init__ section of the class:
class PYTHON_SCRIPT:
def __init__(self):
# put your logic here
Then you could just import the class:
import PYTHON_SCRIPT
# no need to say if a boolean is true, just say if boolean
if option:
PYTHON_SCRIPT()
This would additionally give you the benefit of being able to use properties within your script as you saw fit.
use execfile.
execfile(...)
execfile(filename[, globals[, locals]])
Read and execute a Python script from a file.
The globals and locals are dictionaries, defaulting to the current
globals and locals. If only globals is given, locals defaults to it.
In pyton3, execfile is gone. You can use exec(open('/path/to/file.py').read()) instead.
Already answered here
How do I execute a program from python? os.system fails due to spaces in path
use subprocess module
import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
other methods include making system calls using os library or execfile in the other post
if the script is well designed it probably just launch a main function (often called main), so the most proper way to do this is to import this main function in your code and call it, this is the pythonic way. You just need to add the directory of the script into your python path.
if it's possible, always try to avoid exec, subprocess, os.system, Popen etc ..
example :
import sys
sys.path.insert(0, 'path/to/the/directory')
import python_script
sys.path.pop(0)
if option:
python_script.main()

Linking Python Files Assistance

I understand how to actually link python files, however, i don't understand how to get variable's from these linked files. I've tried to grab them and I keep getting NameError.
How do I go about doing this? The reason i want to link files is to simply neaten up my script and not make it 10000000000 lines long. Also, in the imported python script, do i have to import everything again? Another question, do i use the self function when using another scripts functions?
ie;
Main Script:
import sys, os
import importedpyfile
Imported Py File
import sys, os
I understand how to actually link python files, however, i don't
understand how to get variable's from these linked files. I've tried
to grab them and I keep getting NameError.
How are you doing that? Post more code. For instance, the following works:
file1.py
#!/usr/bin/env python
from file2 import file2_func, file2_variable
file2_func()
print file2_variable
file2.py:
#!/usr/bin/env python
file2_variable = "I'm a variable!"
def file2_func():
print "Hello World!"
Also, in the imported python script, do i have to import everything
again?
Nope, modules should be imported when the python interpreter reads that file.
Another question, do i use the self function when using another
scripts functions?
Nope, that's usually to access class members. See python self explained.
There is also more than one way to import files. See the other answer for some explanations.
I think what you are trying to ask is how to get access to global vars from on .py file without having to deal with namespaces.
In your main script, replace the call to import importedpyfile to say this instead
from importedpyfile import *
Ideally, you keep the code the way you have it. But instead, just reference those global vars with the importedpyfile namespace.
e.g.
import importedpyfile
importedpyfile.MyFunction() # calls "MyFunction" that is defined in importedpyfile.py
Python modules are not "linked" in the sense of C/C++ linking libraries into an executable. A Python import operation creates a name that refers to the imported module; without this name there is no (direct) way to access another module.

Python Idle and Terminal Import Differences

I just started using Python and I have a question about idle vs terminal.
In idle, I made a file called Robot.py
I have a class called Robot
class Robot(object)
def __init__(self,x,y):
#some code here etc...
def HelloWorld()
print "Hello World!"
I have another file called testrobot.py, which looks like so:
import Robot
r = Robot(1,4)
In idle, I am able to successfully create a Robot object when I run testrobot.py. However in terminal, it gives an error Message NameError: Robot is not defined
I'm not sure how to run my program in terminal.
Also:
How can I call my HelloWorld() function which is in Robots.py but not of the class Robot in an external file (such as testrobot.py)?
Thanks in advance!
When you load and run scripts in IDLE, they are automatically loaded for the interpreter. That means that as soon as you run the script in IDLE, the Python shell already has those types defined.
When you want to run it from outside of IDLE, i.e. without running the module first, you need to import your Robot from that module. To do that, you import the module, not the type:
import Robot
myRobot = Robot.Robot(...)
Or, if you want to use Robot directly, you need to use the from ... import syntax:
from Robot import Robot
myRobot = Robot(...)
Similarily, you can call your function by using Robot.HelloWorld in the first case, or directly if you add HelloWorld to the import list in the second case:
from Robot import Robot, HelloWorld
myRobot = Robot(...)
HelloWorld()
As you can see, it is generally a good idea to name your files in lower case, as those are the module names (or “namespaces” in other languages).
You are trying to create a class of an import, not the class imported.
You are trying to import a file called Robot.py with that import statement. To import your robot class you will have to type import Robot and then write Robot.Robot(1,4) to create an object of it. Alternatively you can import all references from the file: from Robot import * and then write Robot(1,4).
The reason it will work with IDLE is that it basically imports everything from the file you run, allowing you use the methods and classes in that file.

Categories