I am not too far into python yet and here is the case.
Say I have one python file called functions.py which holds a class with my functions. Below is an example.
import json
class Functionalities:
def addelement(element):
# code goes here`
And I have another python file, kind of 'executable' script which does all the job using functions from functions.py class
Adding from . import functions doesn't help.
How to I call functions from the class from another file?
Unlike java, you don't have to use classes in python. If a class is used only as a holder for functions, chances are that you want a free function (one without a class) instead.
But to answer your actual question, you can use the import statement. That will run the other .py file, and make the namespace available so you can call things defined there.
functions.py:
import json
class Functionalities:
def addelement(element):
# code goes here`
main.py:
import functions
f = functions.Functionalities()
f.addelement('some element')
Related
I'm working on a project that's written in Go and uses go-python to run Python code inside. The way it works is you write code.py snippits, then the Go code throws in Global variables to use the internal API.
i.e. code.py might look like:
some_api_call() # Linters think some_api_call is not defined, but go-python put it in the global scope
This works great, but for modularity I want my code.py to import code_2.py. Unfortunately, if I do this, code_2.py doesn't have acces to the API that the go code manually added to code.py's global scope.
i.e.
code.py:
import code2.py
code2.run_func()
code2.py:
def run_func():
some_api_call() # This fails since code2.py doesn't have the API injected
I can pass in individual API functions to code_2.py manually, but there's a lot of them. It would be easier if I could just pass everything in code.py's Global scope, like code_2.init(Globals). Is there an easy way to do this? I've tried circular importing, but go-python doesn't let me import the originally called script.
Thanks!
You can pass a paramter to code2.run_func(), and have run_func access api calls through its methods or classmethods.
Something like this. In code.py:
import code2.py
class Api:
#classmethod
def some_api_call(): ...
code2.run_func(Api)
And in code_2.py:
def run_func(api):
api.some_api_call()
Looks like the built-in method globals() will do the trick
code.py:
import code_2
code_2.init(globals())
code_2.py:
def init(other_global_scope):
for k in other_global_scope:
globals()[k] = other_global_scope[k]
# code_2.py can now run some_api_call()
As suggested in the other answer, straight copying globals() can cause weird issues (since a global variable modified in one file will alter the other, as well as imports/etc), so if you're fine prefixing every API call with .api, this will be much more clean:
Top of code.py:
api = lambda: None
for k in globals():
if k.startswith("__") or k == "api":
continue
setattr(api, k, globals()[k])
# api.log("Hello World!")
import code_2.py
code2.run_func(api)
Since you build the api object at the very beginning of code.py, api won't have anything except for what was passed in by the go code. You can now do
code_2.py:
def run_func(api):
api.log("Hello World!")
I've inherited some code with imports in each function and using underscores for each module imported as below
def my_func():
from foo import bar as _bar
from spam import meat as _meat
# Do some work
What is the point in the _bar? All imports are done like this.
If the actual names are things that exist as a part of the built in commands in python, this is done as a way to avoid shadowing those built in functions (for example - from mymodule import open would make the built in open which returns file handles inaccessble). Otherwise, it's simply convention for the original author.
I believe functions with name starting with a single underscore can't be imported using this line :
from module import *
for example this module :
def _some_function_1():
pass
def some_function_2():
pass
if you imported this module, you will be able to access only some_function_2()
I’ve tried to develop a « module expander » tool for Python 3 but I've some issues.
The idea is the following : for a given Python script main.py, the tool generates a functionally equivalent Python script expanded_main.py, by replacing each import statement by the actual code of the imported module; this assumes that the Python source code of the imported is accessible. To do the job the right way, I’m using the builtin module ast of Python as well as astor, a third-party tool allowing to dump the AST back into Python source. The motivation of this import expander is to be able to compile a script into one single bytecode chunk, so the Python VM should not take care of importing modules (this could be useful for MicroPython, for instance).
The simplest case is the statement:
from import my_module1 import *
To transform this, my tool looks for a file my_module1.py and it replaces the import statement by the content of this file. Then, the expanded_main.py can access any name defined in my_module, as if the module was imported the normal way. I don’t care about subtle side effects that may reveal the trick. Also, to simplify, I treat from import my_module1 import a, b, c as the previous import (with asterisk), without caring about possible side effect. So far so good.
Now here is my point. How could you handle this flavor of import:
import my_module2
My first idea was to mimic this by creating a class having the same name as the module and copying the content of the Python file indented:
class my_module2:
# content of my_module2.py
…
This actually works for many cases but, sadly, I discovered that this has several glitches: one of these is that it fails with functions having a body referring to a global variable defined in the module. For example, consider the following two Python files:
# my_module2.py
g = "Hello"
def greetings():
print (g + " World!")
and
# main.py
import my_module2
print(my_module2.g)
my_module2.greetings()
At execution, main.py prints "Hello" and "Hello World!". Now, my expander tool shall generate this:
# expanded_main.py
class my_module2:
g = "Hello"
def greetings():
print (g + " World!")
print(my_module2.g)
my_module2.greetings()
At execution of expanded_main.py, the first print statement is OK ("Hello") but the greetings function raises an exception: NameError: name 'g' is not defined.
What happens actually is that
in the module my_module2, g is a global variable,
in the class my_module2, g is a class variable, which should be referred as my_module2.g.
Other similar side effects happens when you define functions, classes, … in my_module2.py and you want to refer to them in other functions, classes, … of the same my_module2.py.
Any idea how these problems could be solved?
Apart classes, are there other Python constructs that allow to mimic a module?
Final note: I’m aware that the tool should take care 1° of nested imports (recursion), 2° of possible multiple import of the same module. I don't expect to discuss these topics here.
You can execute the source code of a module in the scope of a function, specifically an instance method. The attributes can then be made available by defining __getattr__ on the corresponding class and keeping a copy of the initial function's locals(). Here is some sample code:
class Importer:
def __init__(self):
g = "Hello"
def greetings():
print (g + " World!")
self._attributes = locals()
def __getattr__(self, item):
return self._attributes[item]
module1 = Importer()
print(module1.g)
module1.greetings()
Nested imports are handled naturally by replacing them the same way with an instance of Importer. Duplicate imports shouldn't be a problem either.
In one file I create a class called Robot, but when I try to create an object of that class in another file it says:'module' object has no attribute 'Robot'
main.py
import robot as rob
robot=rob.Robot()
robot.py
class Robot(object):
def __init__(self):
return 0
def otherFunctions():
return 0
And it says: 'module' object has no attribute 'Robot'.
Where I am making a mistake?
The way your code is written is correct (barring removal you've presumably made for conciseness)
When you import, Python checks sys.path for importing locations, and imports the first robot it can find.
A couple ways to solve this:
import robot
print robot.__file__
in robot.py
print("hello!")
import sys
sys.path.insert('/path/to/correct/robot/')
import robot
It seems like the syntax in your robot.py file is not correct. You can correct the errors in the most direct way by changing your robot.py file to look like this:
class Robot(object):
def __init__(self):
pass
def other_functions(self):
pass
Note that I used snake casing for the other_functions function. Don't use camelCasing in Python. It's not idiomatic. Also, I added a self argument to other_functions so you won't get a TypeError if you try to invoke it off of a Robot instance.
Also, unless your code is truly as simple as you present it, the error might be coming from a circular import. Make sure you're not trying to import the two modules from each other before they've had a chance to fully execute.
I'm writing some unittests for code written by someone else here at the office. Python is not my strongest language. While I've been successful with basic unit tests, mocking in python is throwing me for a loop.
What I need to do is override a call to ConfigObj and inject my own mock config/fixture into any ConfigObj call.
settings.py
from configobj import ConfigObj
config = ConfigObj('/etc/myapp/config')
utils.py
from settings import config
"""lots of stuff methods using various config values."""
What I would like to do is, in my unittests for utils.py, inject myself either for ANY call to ConfigObj or settings.py itself.
Many of the mocking libraries expect me to Mock my own classes but in the case of this app, it doesn't have any explicit classes.
Can it be done or are the python namespace restrictions too strict that I can't intervene in what a module that I'm importing imports itself?
Side note: running 2.7 so I can't do any of the tricks I've read about from 2.5.
If the tests are in a separate file from from settings.py and utils.py you can create a file mock.py
import configobj
class MockConfigObj(object):
#mock whatever you wan
configobj.ConfigObj = MockConfigObj
and then import mock before importing (from) any module that itself imports settings. This will ensure that settings.config is created with MockConfigObj. If you want a uniform global mocking, import it before any file that imports configobj.
This works because python will store configobj in sys.modules and check that before actually reading from a file on subsequent imports. in mock.py, the identifier ConfigObj is just a reference to the entry in sys.modules so that any changes that you make will be globally visible.
This strikes me as a little hacky though but it's the best that I can think of.
Python namespaces are not strict at all within the same scope. Just override the variable name containing your object (or the class itself and provided it) within the same scope you'd be expecting the original and that is good enough.
Now, whether or not what you're replacing it with behaves the same is up to you...
Couldn't you just overwrite the original function with another one?
There are no constants in Python, you can change everything, you could even do True = False.
I faced a similar situation before. Here is how I would go about addressing your problem.
Consider a test case for a function from utils.py.
import utils, unittest
class FooFunctionTests(unittest.TestCase):
def setUp(self):
utils._old_config = utils.config
utils.config = MockClass()
def tearDown(self):
utils.config = utils._old_config
del utils._old_config
def test_foo_function_returns_correct_value(self):
self.assertEqual("success!", utils.foo())
The following page is a good one on mocking and import
http://www.relaxdiego.com/2014/04/mocking-objects-in-python.html
Say you have a file named my_package1.py with the following code:
class A(object):
def init(self):
and you then import that in my_package2.py with the code
from my_package1 import A
class A(object):
def init(self):
The first line of my_package2.py creates a variable under the my_package2 namespace called A. Now you have two variables my_package1.A and my_package2.A that both point to the same class in memory. If you want the code in my_package2.py to use a mocked up class A, then you will need to mock my_package2.A not my_package1.A