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
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 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!
I'm dynamically importing any .py modules that are not the __init__.py or my skeleton.py files from a subdirectory. I first build a list that looks like (.py is omitted):
mods_in_dir = ['my_mods.frst_mod','my_mods.scnd_mod']
my_mods beign the subdirectory, frst_mod.py and sncd_mod.py being the available modules. All modules I import contain the class Operation and it offers always the same three functions. Then I import them using importlib.
import importlib
imports = {}
for i in mods_in_dir:
imports[i] = importlib.import_module(i)
Which results in apparently successful imports, as I checked it by print(sys.modules.keys()), where they show up as [...], 'my_mods.frst_mod', 'my_mods.scnd_mod', [...].
For testing reasons I defined a function in every of the modules:
def return_some_string():
return "some string"
But I'm unable to call this function. I've tried everything that came to my mind.. e.g. print(my_mods.frst_mod.Operation.return_some_string()) or print(frst_mod.Operation.return_some_string())
Both resulting in NameError: name 'my_mods' is not defined or NameError: name 'frst_mod' is not defined
edit:
Solved.
#m170897017 helped me solve the problem in my initial attempt.
I missed that I had the modules in the imports dict and didn't use that.
print(imports['my_mods.frst_mod'].ModsClassName.return_some_string()) now successfully prints some_string
Change dynamic import to this way and try again:
...
mods_in_dir = ['my_mods.frst_mod','my_mods.scnd_mod']
modules = list(map(__import__, mods_in_dir))
# if you want to invoke func1 in my_mods.frst_mod and get result from it
result1 = modules[0].func1()
# if you want to invoke func2 in my_mods.scnd_mod and get result from it
result2 = modules[1].func2()
...
Note: Solved. It turned out that I was importing a previous version of the same module.
It is easy to find similar topics on StackOverflow, where someone ran into a NameError. But most of the questions deal with specific modules and the solution is often to update the module.
In my case, I am trying to import a function from a module that I wrote myself. The module is named InfraPy, and it is definitely on sys.path. One particular function (called listToText) in InfraPy returns a NameError, but only when I try to import it into another script. Inside InfraPy, under if __name__=='__main__':, the listToText function works just fine. From InfraPy I can import other functions with no problems. Including from InfraPy import * in my script does not return any errors until I try to use the listToText function.
How can this occur?
How can importing one particular function return a NameError, while importing all the other functions in the same module works fine?
Using python 2.6 on MacOSX 10.6, also encountered the same error running the script on Windows 7, using IronPython 2.6 for .NET 4.0
Thanks.
If there are other details you think would be helpful in solving this, I'd be happy to provide them.
As requested, here is the function definition inside of InfraPy:
def listToText(inputList, folder=None, outputName='list.txt'):
'''
Creates a text file from a list (with each list item on a separate line). May be placed in any given folder, but will otherwise be created in the working directory of the python interpreter.
'''
fname = outputName
if folder != None:
fname = folder+'/'+fname
f = open(fname, 'w')
for file in inputList:
f.write(file+'\n')
f.close()
This function is defined above and outside of if __name__=='__main__':
I've tried moving InfraPy around in relation to the script. The most baffling situation is that when InfraPy is in the same folder as the script, and I import using from InfraPy import listToText, I receive this error: NameError: name listToText is not defined. Again, the other functions import fine, they are all defined outside of if __name__=='__main__': in InfraPy.
This could happen if the module has __all__ defined
Alternatively there could be another version of the module in your path that is getting imported instead of the one you are expecting
Is the NameError about listToText or is it something inside the function causing the exception?
In addition the __all__ variable gnibbler mentioned you could also have a problem with a InfraPy.pyc file lying around somewhere.
I'd recommend putting a import pdb;pdb.set_trace() first in the InfraPy.py file to make sure you are in the right file, and step through the definition of InfraPy.py to see what is happening. If you don't get a breakpoint, you are importing another file than you think.
You can also dir(InfraPy) after importing it, and check which file you are actually importing with InfraPy.__file__.
Can't think of any more import debugging hints right now. ;-)