#include in Python, but really only include - python

I would like to ask:
Is there (in Python) any way, how to absolutelly stupidly include other file into source code? Without any dancings like modules etc,
i.e. equivalent #include from C ?
There were laid many questions about this, but all of them are turning on import modules. No, I want only insert some text lines from any file to my code without preprocess it.
For example:
Let's file mysum.py
c = a + b # there is just this one line
And I want to include to another source code:
file experiment.py:
#!/usr/bin/python
# -*- coding: UTF8 -*-
import importlib
import sys
import math
a = 1
b = 2
import **mysum**
print c
Well, it does not work,
Traceback (most recent call last):
File "./experiment.py", line 12, in <module>
import mysum
File "/home/rna/unix/mypok/mysum.py", line 5, in <module>
c = a + b
NameError: name 'a' is not defined
I really need one short header file include to more different scripts, there would be definitions variables about MySQL connection and similar data, common for more scripts.

execfile used to do this in Python 2, but in Python 3 it's been replaced with:
exec(open('myfile.py').read())
This literally just reads that file (at runtime) and exec's the result. Note that this is not quite the same as what C++ does, which is that the preprocessor does all of this prior to the file being run (or compiled) at all, but it's probably the closest thing there is to it.
If you want to make this some kind of reusable function, you can do something like
import sys
def include(filename):
with open(filename, 'r') as f:
exec(f.read(), sys._getframe(1).f_globals, sys._getframe(1).f_locals)
include("myfile.py") # literally reads the file and evaluates it at runtime
The call to exec(f.read(), sys._getframe(1).f_locals, sys._getframe(1).f_locals) means that the exec call is run in the parent function's scope. See also the answers at What is an alternative to execfile in Python 3?

When you import a module, anything in global scope of the imported module is executed, this includes statements, variable definitions, class definitions, etc.
Example, if I were to modify your mysum.py
a = 1
b = 4
def some_func(a,b):
return a+b
Then in another script run
import mysum
All of those statements would be executed. I would have access to mysum.a, mysum.b, and mysum.some_func because they were executed on import. Your c = a+b acts exactly the same way
Let's now examine the script as you have it:
c = a+b
It is important that you just look at this as a standalone script, even though you are importing it. There is no a or b defined in the entire scope of that script, so when you import, c=a+b gets evaluated, with none of those variables being defined.
I'm not sure the exact use case of what you are trying to do, but if you wanted some function to add two variables, I would do it like so:
#mysum.py
def some_add(a,b):
return a+b
#other_module.py
import mysum
a = 2
b = 3
c = mysum.some_add(a,b)
You'll notice I didn't use a global-style call of a and b like
def some_add():
return a+b
Because that again would require a and b be in the global scope of that module, and you'll again get NameErrors

Related

Calling of Nested Modules in Python

I have been recently working on a project with 150+ files and I am faced with a big hurdle in the switching modules.
I have a feature which allows switching of modules. It works in the following way (I am giving a simplified explanation):
Suppose there are 4 files as first.py, second.py, third.py, fourth.py and each of the following file has a module same as its filename which calls its previous function as below.
Content of first.py
from second import *
def first():
second()
Content of second.py
from third import *
def second():
third()
Content of third.py:
from fourth import *
def third():
q = raw_input('Use (f)ourth or go (b)ack?')
if q == 'f':
fourth() # proceed to fourth
elif q == 'b':
second() # back to second module
# this is how the switching of modules work
Content of fourth.py:
def fourth():
<stuff1>
Now when first() is called, the interpreter asks for f or b. If f, then the <stuff1> is executed, but when b is the input, it gives a NameError something like this.
Traceback (most recent call last):
File "first.py", line 4, in <module>
first()
File "first.py", line 3, in first
second()
File "test/second.py", line 3, in second
third()
File "test/third.py", line 7, in third
second()
NameError: global name 'second' is not defined
And this is basically how the switching back of modules is failing. I have tried importing second.py in third file by adding from second import second which did not help but instead put out an ImportError as ImportError: cannot import name second. Declaring function names as global variables too did not help.
Is there a any way how i can achieve this. Or there is a more efficient way to solve the switching problem.
Edit:
I understand that a circular dependency is being created, but is there any other way to getting the 4 modules up and running without creating this circular dependency.
It seems to me to be a circular import.
The problem is between second.py and third.py. You invoke third in second.py and then second in third.py.
You can read this article to find out what circular imports are and how to prevent them.
P.S. I would suggest not using this syntax for importing stuff from other modules.
from ... import *
This can produce name conflicts and you don't know what is inside this module.
Better option is to import the only things you need or to refer to a specific functions of a module.

Is there a convenient way to translate a "from A import B as C" to an python import using a specific path

I want to import a python module without adding its containing folder to the python path. I would want the import look like
from A import B as C
Due to the specific path that shall be used, the import looks like
import imp
A = imp.load_source('A', 'path')
C = A.B
This is quite unhandy with long paths and module names. Is there an easier way? Is there A way, where the module is not added to the local variables (no A)?
If you just don't want A to be visible at a global level, you could stick the import (imp.load_source) inside a function. If you actually don't want a module object at all in the local scope, you can do that too, but I wouldn't recommend it.
If module A is a python source file you could read in the file (or even just the relevant portion that you want) and run an exec on it.
source.py
MY_GLOBAL_VAR = 1
def my_func():
print 'hello'
Let's say you have some code that wants my_func
path = '/path/to/source.py'
execfile(path)
my_func()
# 'hello'
Be aware that you're also going to get anything else defined in the file (like MY_GLOBAL_VAR). Again, this will work, but I wouldn't recommend it
Someone looking at your code won't be able to see where my_func came from.
You're essentially doing the same thing as a from A import * import, which is generally frowned upon in python, because , you could be importing all sorts of things into your namespace that you didn't want. And even if it works now, if the source code changes, it could import names that shadow your own global symbols.
It's potentially a security hole, since you could be exec'ing an untrusted source file.
It's way more verbose than a regular python import.

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

python interactive mode module import issue

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).

Categories