I'm getting a weird instance of a NameError when attempting to use a class I wrote. In a directory, I have the following file structure:
dir/
ReutersParser.py
test.py
reut-xxx.sgm
Where my custom class is defined in ReutersParser.py and I have a test script defined in test.py.
The ReutersParser looks something like this:
from sgmllib import SGMLParser
class ReutersParser(SGMLParser):
def __init__(self, verbose=0):
SGMLParser.__init__(self, verbose)
... rest of parser
if __name__ == '__main__':
f = open('reut2-short.sgm')
s = f.read()
p = ReutersParser()
p.parse(s)
It's a parser to deal with SGML files of Reuters articles. The test works perfectly. Anyway, I'm going to use it in test.py, which looks like this:
from ReutersParser import ReutersParser
def main():
parser = ReutersParser()
if __name__ == '__main__':
main()
When it gets to that parser line, I'm getting this error:
Traceback (most recent call last):
File "D:\Projects\Reuters\test.py", line 34, in <module>
main()
File "D:\Projects\Reuters\test.py", line 19, in main
parser = ReutersParser()
File "D:\Projects\Reuters\ReutersParser.py", line 38, in __init__
SGMLParser.__init__(self, verbose)
NameError: global name 'sgmllib' is not defined
For some reason, when I try to use my ReutersParser in test.py, it throws an error that says it cannot find sgmllib, which is a built-in module. I'm at my wits' end trying to figure out why the import won't work.
What's causing this NameError? I've tried importing sgmllib in my test.py and that works, so I don't understand why it can't find it when trying to run the constructor for my ReutersParser.
Your problem is not your code, but what you run it in. If you read the error and the code it displays closely:
File "D:\Projects\Reuters\ReutersParser.py", line 38, in __init__
SGMLParser.__init__(self, verbose)
NameError: global name 'sgmllib' is not defined
you'll notice there's no reference to 'sgmllib' on the line that Python thinks produced this error. That means one of two things: either the error didn't originate there (and Python is quite confused), or the code that's being displayed is not the code that is being executed. The latter is quite common when you, for example, run your code in an IDE that doesn't restart the Python interpreter between code executions. It will execute your old code, but when displaying the traceback will show the new code. I'm guessing you did sgmllib.SGMLParser.__init__(self, verbose) on that line at some point in the past.
The reason it was fixed by renaming the class is probably that you did something -- like editing the code -- that caused the IDE to either restart the interpreter, properly clean it up or (by accident) reloaded the right module the right way for it to see the new code. Since you name your module after your class (which is bad style, by the way) I assume you renamed your module when you renamed your class, and so your IDE picked up the new code this time. Until the next time the same thing happens, of course.
Related
I know this question has been asked before, but none of the given answers worked. Say I have a file named Test.py with this code:
class Test():
def __init__(self):
print('Instance Created')
I want to use this class in another file, say Test2.py.
I used the path to the file to get the class, but the message attempted relative import with no known parent package pops up
.
I am using IDLE on Mac OS X.
The path to the file is /Users/*name*/Desktop/Code/Test.py, where *name* is my username for this device.
Code in Test2.py:
from .Users.*name*.Desktop.Code.Test import Test
When I run the program, this message comes up:
Traceback (most recent call last):
File "/Users/*name*/Desktop/Code/Test2.py", line 1, in <module>
from .Users.owen.Desktop.Code.Test import Test
ImportError: attempted relative import with no known parent package
I have tried using sys.path.append but it doesn't seem to work. I have also tried using just .Desktop or .Code instead of the full name, but this gives the same error. I researched packages online, but am struggling to fully comprehend what they are, much less make/use them. Any help would be greatly appreciated.
So the issues that I am currently hitting is with the use of __import__ and even just the standard import. When importing multiprocessing just the main package it will go through however when I run a simple test to see if everything is working for it. I come across an error, below is the current code that IS NOT working.
__import__('multiprocessing')
def my_function():
print('Hello World')
if __name__ == '__main__':
processd = multiprocessing.Process(target=my_function)
processd.start()
processd.join()
it run it will return the following error:
Traceback (most recent call last):
File "F:\Webserv\Python\MP.py", line 7, in <module>
processd = multiprocessing.Process(target=my_function)
NameError: name 'multiprocessing' is not defined
Is there something I am missing with this?
__import__ is a function, therefore you need to capture its return value:
multiprocessing = __import__('multiprocessing')
The standard way is to use the import statement:
import multiprocessing
This is the preferred way. Do programmatic imports only when you really need them. Furthermore, __import__ should not be used:
Import a module. Because this function is meant for use by the Python
interpreter and not for general use it is better to use
importlib.import_module() to programmatically import a module.
I've been working on a project where I have a file which needs to call a function from a file in a sub package/directory, which in turn is calling a function from another file in the same sub package. As such, I have a main file which is importing a sub file. This sub file is also importing another sub file which is in the same package.
The first sub file has no issue whatsoever importing the second sub file. The main file also has no issue importing the first sub file. However, when I put it all together and run the main file, Python thinks that the second sub file doesn't exist, which I find strange. I've simplified and visualised my problem with an example below:
I have the following file hierarchy:
test_package\
__init__.py
main_file.py
test_sub_package\
__init__.py
subfile1.py
subfile2.py
main_file code:
import test_sub_package.subfile1
subfile1 code:
import subfile2
subfile2 code:
def get_string():
return ("Hello, World!")
So, I would expect main_file to import subfile2 via subfile1. However this doesn't seem to be the case because I get an error:
Traceback (most recent call last):
File "...\Test\main_file.py", line 1, in <module>
import test_package.subfile1
File "...\Test\test_sub_package\subfile1.py", line 1, in <module>
import subfile2
ModuleNotFoundError: No module named 'subfile2'
I was a little surprised that I got this error before I even attempted to call the functionality in subfile2. Either way, I'm confused why this doesn't work. Am I just doing something stupid here or am I trying to do something Python fundamentally doesn't support. If anyone can give me a solution it would be most appreciated.
I suspect this is probably a duplicate but I couldn't find an answer to my specific problem. So, sorry in advance.
When you import a module into another module from the same directory you must use must use a relative import in subfile1.py you will need to write:
from . import subfile2
Note, that doesn't give subfile 1 access to get_string to use it in subfile1, you would need to either write subfile2.get_string() or import it directly with:
from .subfile2 import get_string
I have tried this out and it works, I hope this helps :)
Note: that, if you are running a python script, and you need to import a module in that same directory, you can just say import module_name. It makes a difference if it is a script you are running, or a module that is being used in some other script. For a detailed explanation as to why see here
(I assume from your error message that you want to run main.py, if this is not the case you will need to change import test_sub_package.subfile1 to from . import test_sub_package.subfile1)
main file should be:
from test_sub_package.subfile1 import get_string
get_string()
subfile1.py
import test_sub_package.subfile2
I want to write unit tests for a Python script. The script itself runs correctly.
The script consists of one class, which reads a value from the command line into a class variable.
When I import the class into my test file, I get the error 'list index out of range' at the point where the class reads from sys.argv[].
I'm new to testing, in Python and in general. I've read a lot of doc and SO pages about this over the last couple of days.
Here's the code:
File bongo.py --
import sys
class Bongo:
my_int = int(sys.argv[1])
def __init__(self, n):
self.n = n
def get_sum(self):
return self.n + Bongo.my_int
if __name__ == '__main__':
bongo = Bongo(5)
m = bongo.get_sum()
print('bongo.get_sum() returns {}'.format(m))
File bongo_test.py --
import unittest
from bongo import Bongo
class TestBongoMethods(unittest.TestCase):
def setUp(self):
self.bongo = Bongo(10)
self.bongo.my_int = 5
def test_get_n(self):
self.assertEqual(self.bongo.get_sum(), 15)
if __name__ == '__main__':
unittest.main()
The output of running python bongo_test.py is
Traceback (most recent call last):
File "bongo_test.py", line 2, in <module>
from bongo import Bongo
File "/home/me/class_for_testing/bongo.py", line 4, in <module>
class Bongo:
File "/home/me/class_for_testing/bongo.py", line 6, in Bongo
my_int = int(sys.argv[1])
IndexError: list index out of range
I've tried just about everything I can think of; I've been using Py 2.7 in PyCharm Pro 2016.1,
but the results are no different using Py 3.4 or running from the command line.
Can this be done using unittest? Or do I need something else?
Any help would be much appreciated!
Generally, unit testing is helpful in figuring out the boundaries of your classes. If your class is hard to unit test, you should think: "how can I make it easier to test?" Almost always this leads to better structured classes.
One of these symptoms is that you have external dependencies, like sys.argv, that are hard to control. Generally you want to inject dependencies like this into a class. This is one of the advantages of object-oriented programming -- that you can isolate dependencies and minimize the complexity of the objects themselves.
The __main__ block is perfect for command-line specific logic, like sys.argv. I would recommend reading the variable there, and passing it into the constructor of Bongo. Then you can unittest Bongo as a class that takes two variables, and have it be ignorant of sys.argv.
For command line args I suggest you argparse package (included in plain Python.)
The __main__ part will contain parsing by and the call of the main method.
You will can test separately both:
arg parsing
business logic with given parameters
I had assumed that in Python if I do some
class A:
print("hi")
this "hi" would only ever be printed more than once if I explicitly deleted A with some del A
In my slightly bigger project I have this code (names changed):
class A(ISomething):
print(threading.current_thread())
try:
A.MY_DICT # yeah, this should never ever result in anything but an error but neither should this code be run twice
print(A.MY_DICT)
except NameError:
print("A.MY_DICT unknown")
MY_DICT = {}
and it produces this output:
$ python main.py
<_MainThread(MainThread, started 140438561298240)>
A.MY_DICT unknown
<_MainThread(MainThread, started 140438561298240)>
A.MY_DICT unknown
so on the same thread the same class level code gets executed twice. How is that possible when I never del A? The code had worked before but I don't have commits to narrow down the change that broke it.
The same code with MY_DICT instead of A.MY_DICT fails equally and as PyDev already at time of writing tells me that this will not work, I am pretty confident that there's something fishy going on.
You are probably importing the file under different names, or running it as both the __main__ file and importing it.
When Python runs your script (the file named on the command line) it gives it the name __main__, which is a namespace stored under sys.modules. But if you then import that same file using an import statement, it'll be run again and the resulting namespace is stored under the module name.
Thus, python main.py where main.py includes an import main statement or imports other code that then in turn imports main again will result in all the code in main.py to be run twice.
Another option is that you are importing the module twice under different full names; both as part of a package and as a stand-alone module. This can happen when both the directory that contains the package and the package itself are listed on your sys.path module search path.