python interactive mode module import issue - python

I believe I have what would be called a scope issue, perhaps name space. Not too sure I'm new to python.
I'm trying to make a module that will search through a list using regular expressions. I'm sure there is a better way of doing it but this error that I'm getting is bugging me and I want to understand why.
here's my code:
class relist(list):
def __init__(self, l):
list.__init__(self, l)
def __getitem__(self, rexp):
r = re.compile(rexp)
res = filter(r.match, self)
return res
if __name__ == '__main__':
import re
listl = [x+y for x in 'test string' for y in 'another string for testing']
print(listl)
test = relist(listl)
print('----------------------------------')
print(test['[s.]'])
When I run this code through the command line it works the way I expect it to; however when I run it through python interactive mode I get the error
>>> test['[s.]']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "relist.py", line 8, in __getitem__
r = re.compile(rexp)
NameError: global name 're' is not defined
While in the interactive mode I do import re and I am able to use the re functions, but for some reason when I'm trying to execute the module it doesn't work.
Do I need to import re into the scope of the class? I wouldn't think so because doesn't python search through other scopes if it's not found in the current one?
I appreciate your help, and if there is a better way of doing this search I would be interested in knowing. Thanks

Move the "import re" out of the bottom "if..." to the top of the file:
import re
class ....
You're only importing the re module when run as a program, not imported as a module.
(Also, Python style prefers upper-case class names.)

Python does not run anything "ahead of time"; it runs code when it encounters it. The only thing that's done "ahead of time" is to translate the source code into bytecode.
When you import the module, __name__ is the name of the module, rather than __main__. Thus, the code in the if block at the end is not executed, and re is not imported. When you then attempt to use the class, the name re is looked up right then, when it's needed (to access re.compile), and not found (because the module wasn't imported earlier).

Related

Python: NameError when trying to use "re" inside a function

I have a script called main_plotter.py that looks like this:
import re
import numbs
numbs.getSquares("file.csv")
numbs.py is the file that I'm importing from. It looks like this:
def getSquares(sqfile):
infile=sqfile
base_name = re.split(".csv", infile)[0]
print (base_name)
When I run main_plotter.py, I get NameError: name 're' is not defined.
Why is this happening? I tried adding global re before the import re statement, but that doesn't help either. Aren't the import statements supposed to be global anyway? Any help appreciated!
PS. the code runs as expected if I import re inside the numbs.py file.
"Global" in Python means "module namespace". Any import re happens exactly there -- module-by-module; there intentionally does not exist any wider scope, which ensures that the content of any Python module can be understood by reading only that module (unlike Ruby, where to know the context in which code is run you need to read every module that was ever loaded by the same interpreter).
If you want to use the re module in numbs.py, you should have a separate import re inside that file. This doesn't reload the module from disk, but just adds a namespace entry pointing to the already-cached instance that was loaded on first reference.

Searching docx Files in python

I am trying to use the python-docx module to search docx files for specific strings:
https://github.com/python-openxml/python-docx
But for some reason none of the functions I try to use within the module seem to be working (opendocx, search, etc). I have installed the module and have imported it in my script so I can't figure out what's going wrong. For example though when I try to use opendocx() I get an error saying the module has no attribute 'opendocx'
Other people seem to be able to use this module fine, am I missing something obvious?
EDIT:
Here is the code where I am trying to use the doc:
def parseFile2(filename):
document = opendocx(filename)
for key in SEARCH_STRINGS:
if search(document, key):
return True
The filename is passed in from another function with a full path and again the error I am getting is that the module has no attribute opendocx
After a quick look at the documentation of the module you're not using the Document class of the module.
from docx import Document
def parseFile2(filename):
document = Document(filename)
for key in SEARCH_STRINGS:
if search(document, key): # dont know if this part works, cause i didn't install the module
return True
You may be doing import modulename rather than from modulename import class. This can often lead to the behavior you're seeing. For example:
>>> import math
>>> sqrt(64)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sqrt' is not defined
>>> from math import sqrt
>>> sqrt(64)
8.0

NameError when importing a dict

I've got a script where I want to import a dict from a file and then use it to execute functions.
The file codes.py is as follows:
rf_433mhz = {
"0x471d5c" : sensor_LaundryDoor,
}
And the file it's using is as follows:
#!/usr/bin/python
import mosquitto
import json
import time
def sensor_LaundryDoor():
print "Laundry Door Opened"
mqttc.publish("actuators", json.dumps(["switch_HallLight", "on"]))
from codes import rf_433mhz
but I'm getting a NameError.
Traceback (most recent call last):
File "sensors.py", line 11, in <module>
from codes import rf_433mhz
File "/root/ha/modules/processing/codes.py", line 2, in <module>
"0x471d5c" : sensor_LaundryDoor,
NameError: name 'sensor_LaundryDoor' is not defined
Is there any way to do what I'm trying to do? It seems to be getting stuck on not having the function inside codes.py
I'm trying to call sensor_LaundryDoor() as follows
def on_message(msg):
inbound = json.loads(msg.payload)
medium = inbound[0]
content = inbound[1]
if str(medium) == "433mhz":
try:
rf_433mhz[str(content)]()
except:
print "Sorry code " + content + " is not setup"
import isn't include. It won't dump the source code of codes.py into your script; rather, it runs codes.py in its own namespace, almost like a separate script, and then assigns either the module object or specific module contents to names in the namespace the import is in. In the namespace of codes.py, there is no sensor_LaundryDoor variable.
The way you're dividing the code into modules isn't very useful. To understand codes.py, you need to understand the other file to know what sensor_LaundryDoor is. To understand the other file, you need to understand codes.py to know what you're importing. This circular dependency would negate most of the benefit of modularizing your code even if it wasn't an error. Reorganize your code to fix the circular dependency, and you'll probably fix the NameError as well.
The problem is that in your dictionary that you're importing, you're setting the value of 0x471d5c to a variable that was either not defined, or not defined in that scope.
An example of this would be like:
Codes.py
#!/usr/bin/python
sensor_LaundryDoor = 'foo'
rf_433mhz = {
"0x471d5c" : sensor_LaundryDoor,
}
Main files
#!/usr/bin/python
from test import rf_433mhz
print rf_433mhz["0x471d5c"]
There are hacky ways to solve this but it looks like the real issue is that you're trying to write C-style code in Python. The Python way to do things would be to import sensor_LaundryDoor in codes.py before using it, and if this introduces a circular reference then that's a design issue.
Maybe you need three modules, events.py with your main loop which imports the dict from codes.py which imports the functions from sensors.py.

How to run a large amount of python code from a string?

I need to be able to run a large amount of python code from a string. Simply using exec doesn't seem to work, as, while the code runs perfectly in a normal setting, doing it this way seems to throw an error. I also don't think I can just import it as it it hosted on the internet. Here is the code:
import urllib.request
URL = "https://dl.dropboxusercontent.com/u/127476718/instructions.txt"
def main():
instructions = urllib.request.urlopen(URL)
exec(instructions.read().decode())
if __name__ == "__main__":
main()
This is the error I've been getting:
Traceback (most recent call last):
File "C:\Python33\rc.py", line 12, in <module>
main()
File "C:\Python33\rc.py", line 9, in main
exec(instructions.read().decode())
File "<string>", line 144, in <module>
File "<string>", line 120, in main
NameError: global name 'Player' is not defined
The code I'm trying to run is available in the link in the first code snippet.
If you have any questions I'll answer them. Thank you.
Without specifying globals, the exec function (Python/bltinmodule.c) uses PyEval_GetGlobals() and PyEval_GetLocals(). For the execution frame of a function, the latter creates a new f_locals dict, which will be the target for the IMPORT_NAME, STORE_NAME, LOAD_NAME ops in the compiled code.
At the module level in Python the normal state of affairs is globals() == locals(). In that case STORE_NAME is using the module's globals, which is what a function defined within the module will use as its global namespace. However, using separate dicts for globals and locals obviously breaks that assumption.
The solution is to to manually supply globals, which exec will also use as locals:
def main():
instructions = urllib.request.urlopen(URL)
exec(instructions.read().decode(), globals())
You could also use a new dict that has __name__ defined:
def main():
instructions = urllib.request.urlopen(URL)
g = {'__name__': '__main__'}
exec(instructions.read().decode(), g)
I see in the source that the current directory will need a sound file named "pickup.wav", else you'll just get another error.
Of course, the comments about the security problems with using exec like this still apply. I'm only addressing the namespace technicality.
First I thought you might try __import__ with a StringIO object. Might look something like StackOverflow: Local Import Statements in Python.
... but that's not right.
Then I thought of using the imp module but that doesn't seen to work either.
Then I looked at: Alex Martelli's answer to Use of Eval in Python --- and tried to use it on a silly piece of code myself.
I can get the ast object, and the results of the compile() from that (though it also seems that one can simply call compile(some_string_containing_python_source, 'SomeName', 'exec') without going through the ast.parse() intermediary step if you like. From what I gather you'd use ast if you wanted to then traverse the resulting syntax tree, inspecting and possibly modifying nodes, before you compiled it.
At the end it seems that you'll need to exec() the results of your compile() before you have resulting functions, classes or variables defined in your execution namespace.
You can use pipe to put all strings into a child process of python and get output result from it.
Google os.popen or subprocess.Popen

Import statement in library definition does not seem to be executed

I am having a problem that may be quite a basic thing, but as a Python learner I've been struggling with it for hours. The documentation has not provided me with an answer so far.
The problem is that an import statement included in a module does not seem to be executed when I import this module from a python script. What I have is as follows:
I have a file project.py (i.e. python library) that looks like this:
import datetime
class Project:
""" This class is a container for project data """
title = ""
manager = ""
date = datetime.datetime.min
def __init__( self, title="", manager="", date=datetime.datetime.min ):
""" Init function with some defaults """
self.title = title
self.manager = manager
self.date = date
This library is later used in a script (file.py) that imports project, it starts like this:
import project
print datetime.datetime.min
The problem then arises when I try to execute this script with Python file.py. Python then complains with the folliwing NameError:
Traceback (most recent call last):
File "file.py", line 3, in <module>
print datetime.datetime.min
NameError: name 'datetime' is not defined
This actually happens also if I try to make the same statements (import and print) directly from the Python shell.
Shouldn't the datetime module be automatically imported in the precise moment that I call import project?
Thanks a lot in advance.
The datetime module is only imported into the project namespace. So you could access it as project.datetime.datetime.min, but really you should import it into your script directly.
Every symbol (name) that you create in your project.py file (like your Project class) ends up in the project namespace, which includes things you import from other modules. This isn't as inefficient as it might seem however - the actual datetime module is still only imported once, no matter how many times you do it. Every time you import it subsequent to the first one it's just importing the names into the current namespace, but not actually doing all the heavy lifting of reading and importing the module.
Try thinking of the import statement as roughly equivalent to:
project = __import__('project')
Effectively an import statement is simply an assignment to a variable. There may be some side effects as the module is loaded, but from inside your script all you see is a simple assignment to a name.
You can pull in all the names from a module using from project import *, but don't do that because it makes your code much more brittle and harder to maintain. Instead either just import the module or exactly the names you want.
So for your code something like:
import datetime
from project import Project
is the sort of thing you should be doing.

Categories