Main program variables in side programs (Python) - python

How do I use variables that exist in the main program in the side program? For example, if I were to have Var1 in the main program, how would I use it in the side program, how would I for example, print it?
Here's what I have right now:
#Main program
Var1 = 1
#Side program
from folder import mainprogram
print(mainprogram.Var1)
This I think would work, if it didn't run the main program when it imports it, because I have other functions being executed in it. How would I import all the main program data, but not have it execute?
The only thing I thought of was to import that specific variable from the program, but I don't know how to do it. What I have in my head is:
from folder import mainprogram
from mainprogram import Var1
But it still excecutes mainprogram.

Your approach is basically correct (except for from folder import mainprogram - that looks a bit strange, unless you want to import a function named mainprogram from a Python script named folder.py). You have also noticed that an imported module is executed on import. This is usually what you want.
But if there are parts of the module that you only want executed when it's run directy (as in python.exe mainprogram.py) but not when doing import mainprogram, then wrap those parts of the program in an if block like this:
if __name__ == "__main__":
# this code will not be run on import

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?

How importing actually works in python?

In my working directory, I have python3 files like this
/Path/to/cwd/main.py
/Path/to/cwd/Folder/one.py
/Path/to/cwd/Folder/two.py
So I had a main.py file like this
import Folder.one as one
#Do something
In one.py I had code like this
import two
#Some functions defined locally utilizing functions written in two.py
if __name__ == '__main__':
#Code for testing Functions
When I run one.py, it runs fine. But when I run main.py, it throws an error
ModuleNotFoundError: No module named 'two'
Ideally, I would not be expecting such an error at all.
It worked when I changed the import statement from import two to import Folder.two, which works. But I would like to do this in some other way without affecting such import statements much. How to achieve this?
In order for the python interpreter to know what directories contain code to be loaded, you need to include a __init__.py file.
Have a look at this answer to learn more about how to import packages.
In the case of your second import, to access that method you would need to use this syntax.
from .two import *

Importing variables from another Python script

Is it possible to import a Python script into a main script and then just use the variables? I don't want the other script to execute inside of the main script, just attach one of the variables...
If you can edit the script being imported, there's a solution:
Put all the executed code into a block starting with
if __name__ == '__main__':
In this way, the code in the if block above will be executed only if the script is run directly. i.e. when you run python script.py.
You can import only the variable like this:
from script import var
If you want to import the variable without going through the whole script, then as per Python's design it's not possible. import will always go through the whole script being imported, and will avoid whatever that's inside __name__ == '__main__'.
You have an option to read the script file and find the variables, then do it yourself by parsing and executing it, but IMO that's unnecessary job to do since you have import.
You can see the answers under Python: import module without executing script

Way around Python imports within imports?

Sorry if this is a very novice question, I was just wondering one thing.
When in python and your code is split up amongst multiple files, how would you avoid a ton of imports on the same thing?
Say I have 2 files. Main, and Content.
Main:
import pygame
from pygame.locals import *
pygame.display.init()
blah
Content:
import pygame
from pygame.locals import *
pygame.display.init()
load content and stuff
pygame is imported twice and display.init is called twice. This is problematic in other places. Is there anyway to get around this, or must it just import and import and import?
One situation I can think of is this: A script that writes to a file everytime it is imported. That way, if it's imported 3 times, it gets run 3 times, therefore writing to the file 3 times.
Thanks in advance!
You misunderstand what import does. It's not the same as include. Loaded modules are singletons and their corresponding files are not evaluated twice.
That said, a well-constructed module will not have side-effects on import. That's the purpose of the if __name__=='__main__' idiom.
Do not attempt to "clean up" your imports. Import everything you need to use from within a file. You could make less use of import *, but this is purely for code readability and maintainability.
You should avoid having anything happen at import(except, see further down). a python file is a module first, so it can and should be used by other python modules. If something "happens" in the import stage of a python file, then it may happen in an undesirable way when that file is imported by another module.
Each module should just define things to be used: classes, functions, constants, and just wait for something else to use them.
Obviously, if no script ever does at import, then it's not possible for anything to actually get used and make stuff "happen". There is a special idiom for the unusual case that a module was called directly. Each python file has a variable, __name__ automatically created with the module name it was imported as. When you run a script from the command line (or however you have started it), it wasn't imported, and there's no name for it to have, and so the __name__ variable will have a special value "__main__" that indicates that it's the script being executed. You can check for this condition and act accordingly:
# main.py
import pygame
from pygame.locals import *
import content
def init():
pygame.display.init()
def stuff():
content.morestuff()
if __name__ == '__main__':
init()
stuff()
# content.py
import pygame
from pygame.locals import *
def init():
pygame.display.init()
def morestuff():
"do some more stuff"
if __name__ == '__main__':
init()
morestuff()
This way; init() and thus pygame.display.init() are only ever called once, by the script that was run by the user. the code that runs assuming that init() has already been called is broken into another function, and called as needed by the main script (whatever that happens to be)
import statements are supposed to be declarations that you're using something from another module. They shouldn't be used to cause something to happen (like writing to a file). As noted by Francis Avila, Python will try not to execute the code of a module more than once anyway.
This has the consequence that whether a given import statement will cause anything to happen is a global property of the application at runtime; you can't tell just from the import statement and the source code of the module, because it depends on whether any other code anywhere else in the project has already imported that module.
So having a module "do something" when executed is generally a very fragile way to implement your application. There is no hard and fast definition of "do something" though, because obviously the module needs to create all the things that other modules will import from it, and that may involve reading config files, possibly even writing log files, or any number of other things. But anything that seems like the "action" of your program, rather than just "setting up" things to be imported from the module, should usually not be done in module scope.

how to execute nested python files

I have 3 python files.(first.py, second.py, third.py) I'm executing 2nd python file from the 1st python file. 2nd python file uses the 'import' statement to make use of 3rd python file. This is what I'm doing.
This is my code.
first.py
import os
file_path = "folder\second.py"
os.system(file_path)
second.py
import third
...
(rest of the code)
third.py (which contains ReportLab code for generating PDF )
....
canvas.drawImage('xyz.jpg',0.2*inch, 7.65*inch, width=w*scale, height=h*scale)
....
when I'm executing this code, it gives error
IOError: Cannot open resource "xyz.jpg"
But when i execute second.py file directly by writing python second.py , everything works fine..!!
Even i tried this code,
file_path = "folder\second.py"
execfile(file_path)
But it gives this error,
ImportError: No module named third
But as i stated everything works fine if i directly execute the second.py file. !!
why this is happening? Is there any better idea for executing such a kind of nested python files?
Any idea or suggestions would be greatly appreciated.
I used this three files just to give the basic idea of my structure. You can consider this flow of execution as a single process. There are too many processes like this and each file contains thousandth lines of codes. That's why i can't change the whole code to be modularize which can be used by import statement. :-(
So the question is how to make a single python file which will take care of executing all the other processes. (If we are executing each process individually, everything works fine )
This should be easy if you do it the right way. There's a couple steps that you can follow to set it up.
Step 1: Set your files up to be run or imported
#!/usr/bin/env python
def main():
do_stuff()
if __name__ == '__main__':
The __name__ special variable will contain __main__ when invoked as a script, and the module name if imported. You can use that to provide a file that can be used either way.
Step 2: Make your subdirectory a package
If you add an empty file called __init__.py to folder, it becomes a package that you can import.
Step 3: Import and run your scripts
from folder import first, second, third
first.main()
second.main()
third.main()
The way you are doing thing is invalid.
You should: create a main application, and import 1,2,3.
In 1,2,3: You should define the things as your functions. Then call them from the main application.
IMHO: I don't need that you have much code to put into separate files, you just also put them into one file with function definitions and call them properly.
I second S.Lott: You really should rethink your design.
But just to provide an answer to your specific problem:
From what I can guess so far, you have second.py and third.py in folder, along with xyz.jpg. To make this work, you will have to change your working directory first. Try it in this way in first.py:
import os
....
os.chdir('folder')
execfile('second.py')
Try reading about the os module.
Future readers:
Pradyumna's answer from here solved Moin Ahmed's second issue for me:
import sys, change "sys.path" by appending the path during run
time,then import the module that will help
[i.e. sys.path.append(execfile's directory)]

Categories