I have a python code, say first.py, that call, during his execution a second one, say second.py.
second.py is used as a big function that return back a certain object.
In particular, the structure of first.py is the following (where ... indicate a part of the code not relevant (where I define the variable to give in input for example)):
import second as nb
...
x = nb.BP(a, b, c)
...
While the structure of second.py is the following:
def BP (A, B, C)
...
return obj
Now, in my working folder, say MainFold , I have this 2 code. Inside MainFold there is also another folder, say SubFold. Inside SubFold I have a modified version of first.py and second.py which mantain the same names.
The difference in these codes is that the function BP inside second.py now takes only 2 arguments.
I start running the first.py's MainFold version. Then, I launch the version inside SubFold. What I get is a TypeError:
TypeError: BP() missing 1 required positional arguments: 'C'
It seems like the varied version of first.py inside SubFold calls the second.py's version inside MainFold instead of the code inside its folder (SubFold).
Why does it happens? Is there a way to force first.py to call only codes inside its same folder?
When you try to import a module that is in the same folder simply write:
import second as nb
To access the files from the subfolder use:
import subfolder.second as nb
Specify the path to the folder:
Let's say you are in subfold and the program is second.py
then give it address as "/subfold/second.py"
Try this if the error persists, ping me again!
Related
I have the program, which does stuff. And it counts how many times it has done some things by day and by hour. So I created a class and assigned it to hourly and daily.
And besides that, I have a multi thread function (let's call it background) which is used for the menu in the console. It is used to see/print or even modify variables. But it doesn't work. Every time I want it to print the class attributes, it always prints 0 for all attributes. How to fix this?
I also have this class and functions in separate modules
module a:
class Data():
def __init__(self,some_count):
self.some_count=some_count
daily=Data(0)
hourly=Data(0)
module b:
from a import daily,hourly
def print_data(command):
if command == "daily" :print(f"Daily saying hi is: {daily.some_count}")
if command == "hourly" :print(f"Hourly saying hi is: {hourly.some_count}")
background(): #It is used for menu. Depending on what you want, it can also print class attributes
while True:
print_data(input()) #you need to choose the command
module c:
from a import daily,hourly
from b import background
threading1 = threading.Thread(target=background) #
threading1.daemon = True #
threading1.start() #these 3 lines are copy pasted from my code
#this is the main function. And if you insert print(hourly.some_count) it will print the right value
while True:
hourly.some_count+=1
daily.some_count+=2
time.sleep(10000)
Note, this is not my code. Well it is, but just the idea. The above code is not functional, i just wanted to show, how i coded it.
I just don't know, why the function to print doesn't work. I assume that the "daily" and "hourly" class are mutated for a thread?
Perhaps it is a problem with imports? I have defined a class in module a, imported the "daily" and "hourly" in class b where I used in function. And then imported that function into module c where the main program is?
Thank you for help
EDIT, FOR THOSE WHO WANT AN ANSWER:
the solution below did not help.
I found a mistake myself later on and fixed it this way:
I made a seperate module, where i declared all the variables and classes. Only declaragion, no fuctions or any off that. And then i imported a varible or clas like this: From "class_declaration" import "name of class"
That way i can share the variable accros modules and threads
your concepts are correct: instance attributes changed in one thread should be visible in another thread. What I think might be wrong in your setup has to do with module naming and importing: some of the imports are ending internally as "myproject.a" and others just as "a": internally Python will create separate modules and separate objects.
If you uniformize the module names and containing directory in a Python package, everything should work as expected.
Try this: put all your .py modules in a folder containing an empty (0 bytes) file named __init__.py - and write your entry-point (the code from which your program will start running) in a file named __main__.py. Rewrite your imports to read from .a import daily, hourly (see the ".") -
and then from the parent of that directory, run the project with python -m <directory_name> - Python should execute the code in __main__.py and see all the other modules as part of the same package.
I have two python files under the same directory. One is called a.py and the other is called aa.py. They both import something from each other like:
# a.py
x = 1
from aa import var
y=1
# aa.py
import a
var = 1
print(a.x)
print(a.y)
If I run python aa.py It will pop up error AttributeError: module 'a' has no attribute 'y'.
I am very confused why x is successfully imported while y cannot. It feels like because in a.py, x is declared before from aa import var but why is that?
Thanks.
Someone with a lot more back-end programming experience could probably add a lot more, but my thought is that any Python being imported is going to be compiled before you can call it, and it's going to note the call for a before it has been defined.
FYI, you're going to run into circular dependencies if you keep writing your code like this: https://stackabuse.com/python-circular-imports
If you need something in both files, put it in a third file that can be called from both but that doesn't call either of the first two.
I'm still a beginner in Python. I'm working on a main script in which the function (b) needs to call another function (a) inside it but when I run it I get a 'NameError'. This is what I've done in the main script:
# main script
from __file_a import a
from __file_b import b
par = 'some parameters'
x = b(par)
This is what I've written in the b function
def b(some parameters):
from __file_a import a
out = a(par2)
return out
I've tried to remove the call of a from b and also tried to redefine a in b but when I run the main script I still get an error "NameError: name 'a' is not defined. All the files are in the same folder and all the files are named "__functioname.py".
Can anyone suggest me how to solve this issue?
Many thanks
Not sure if that is just an example name but don't name your files with trailing underscores. Secondly, is there an __init__.py in that folder? You need it for importing from scripts in that folder
I have the following code:
Script1
def encoder(input_file):
# a bunch of other code
# some more code
# path to output of above code
conv_output_file = os.path.join(input_file_gs, output_format)
subprocess.run(a terminal file conversion runs here)
if __name__ == "__main__":
encoder("path/to/file")
And this is how I try to import and how I set it in script2.
Script2
from script1 import encoder
# some more code and imports
# more code
# Here is where I use the output_location variable to set the input_file variable in script 2
input_file = encoder.conv_output_file
What I am trying to do is use variable output_location in another python3 file. So I can tell script2 where to look for the file that it is trying to process without hardcoding it in.
Every time I run the script though I get the following error:
NameError: name 'conv_output_file' is not defined
What I get from your description is that you want to get a local variable from another python file.
Return it or make it a global variable, and import it.
Maybe you have some difficulty in importing it correctly.
Make these two points clear:
you could only import packages in two ways: the package in PYTHONPATH or the local package. Especially, if you want do any relative import, add . before your package name to specify the package you want to import.
Python interpreter treat a directory as a package only if there is a __init__.py under the directory.
what you actually want to do with the variable conv_output_file? if you just want to get the value/object to which conv_output_file binds, then you better use return statement. or if you want to access the variable and do some more thing on that variable i.e modifying it then you can use global to access the variable conv_output_file.
def encoder(input_file):
# a bunch of other code
# some more code
# path to output of above code
global conv_output_file
conv_output_file = os.path.join(input_file_gs, output_format)
you can access the variable now from 2nd script as firstscript.conv_output_file only after calling that function firstscript.encoder(...) because until the function is not invoked variable does not eists . but it is not recommended to use global, you should avoid the use of global.
I think you want to get that value not access variable so better use return statement
def encoder(input_file):
# a bunch of other code
# some more code
# path to output of above code
return conv_output_file
conv_output_file = os.path.join(input_file_gs, output_format)
return conv_output_file
or simply
return os.path.join(input_file_gs, output_format)
I think apart from not returning the variable or not declaring it as a class variable, you're probably making another mistake.
tell that 2nd script
You have to properly import the 1st script into your second script and use the encoder function as an attribute of the 1st script.
For example, name your first script encoder_script.
In second script,
import encoder_script
encoder_script.encode(filename)
I'm sure this is very simple but I've been unable to get it working correctly. I need to have my main python script call another python script and pass variables from the original script to the script that I've called
So for a simplistic example my first script is,
first.py
x = 5
import second
and my second script is,
second.py
print x
and I would expect it to print x but I get
NameError: name 'x' is not defined
I'm not sure if import is right way to achieve this, but if someone could shed light on it in a simple way that would be great!
thanks,
EDIT
After reading the comments I thought I would expand on my question. Aswin Murugesh answer fixes the import problem I was having, however the solution does not have the desired outcome as I can not seem to pass items in a list this way.
In first.py I have a list which I process as follows
for insert, (list) in enumerate(list, start =1):
'call second.py passing current list item'
I wanted to pass each item in the list to a second python file for further processing (web scraping), I didn't want to do this in first.py as this is meant to be the main 'scan' program which then calls other programs. I hope this now make more sense.
Thanks for the comments thus far.
When you call a script, the calling script can access the namespace of the called script. (In your case, first can access the namespace of second.) However, what you are asking for is the other way around. Your variable is defined in the calling script, and you want the called script to access the caller's namespace.
An answer is already stated in this SO post, in the question itself:
Access namespace of calling module
But I will just explain it here in your context.
To get what you want in your case, start off the called script with the following line:
from __main__ import *
This allows it to access the namespace (all variables and functions) of the caller script.
So now your calling script is, as before:
x=5
import second
and the called script is:
from __main__ import *
print x
This should work fine.
use the following script:
first.py:
x=5
second.py
import first
print first.x
this will print the x value. Always imported script data should be referenced with the script name, like in first.x
To avoid namespace pollution, import the variables you want individually: from __main__ import x, and so on. Otherwise you'll end up with naming conflicts you weren't aware of.
Try use exec
Python3.5:
first.py
x=5
exec(open('second.py').read())
second.py
print(x)
You can also pass x by using:
x=5
myVars = {'x':x}
exec(open('second.py').read(), myVars)
Not sure if this is a good way.
Finally,
I created a package for Python to solve this problem.
Install Guli from PIP.
$ pip install guli
Guli doesn't require installing any additional PIP package.
With the package you can
Guli can be used to pass between different Python scripts, between many processes or at the same script.
pass variables between main Process and another (Multiprocess) Process.
Pass variables between different Python scripts.
Pass variables between 'Main Process' and another (Multiprocess) Process.
Use variables at the same script.
Create / Delete / Edit - GuliVariables.
Example
import guli
import multiprocessing
string = guli.GuliVariable("hello").get()
print(string) # returns empty string ""
def my_function():
''' change the value from another process '''
guli.GuliVariable("hello").setValue(4)
multiprocessing.Process(target=my_function).start()
import time
time.sleep(0.01) # delay after process to catch the update
string = guli.GuliVariable("hello").get()
print(string) # returns "success!!!"
Hope I solved the problem for many people!