I tried to use configparser module from standard library in python 3.6 or python 3.5.1
My ini file looks like this:
[common]
domain = http://some_domain_name:8888
about = about/
loginPath = /accounts/login/?next=/home
fileBrowserLink = /filebrowser
partNewDirName = some_dir
[HUE_310]
partNewFilePath = ${common:domain}
My "main" program looks like this:
from configparser import ConfigParser
parser = ConfigParser()
parser.read('configfile.ini')
lll = parser.get('HUE_310', 'partNewFilePath')
print(lll)
Instead http://some_domain_name:8888 I got ${common:domain}
I use Pycharm Community as my IDE. I use virtualenv.
I have no idea what is wrong with my code...
If you want extended interpolation, you have to create an instance of the configparser.ExtendedInterpolation class, by calling it, and then using that with the interpolation= keyword argument when you create the ConfigParser instance as shown below:
from configparser import ConfigParser, ExtendedInterpolation
parser = ConfigParser(interpolation=ExtendedInterpolation())
parser.read('configfile.ini')
lll = parser.get('HUE_310', 'partNewFilePath')
print(lll) # -> http://some_domain_name:8888
Related
I have a build.properties file like
[directory]
src = src
srcdir = ${src}/fix
srcext = ${srcdir}/extensions
srct = ${srcext}/xyz
my aim is to get the full value of srct i mean it is to be src/fix/extensions/xyz
Is there any way of getting the value of cde? I tried configparser and jproperties but i couldn't get the required output.
You can use ExtendedInterpolation class which implements more advanced syntax.
>>> from configparser import ConfigParser, ExtendedInterpolation
>>>
>>> parser = ConfigParser(interpolation=ExtendedInterpolation())
>>> parser.read("build.properties")
['build.properties']
>>> print(parser["directory"]["srct"])
src/fix/extensions/xyz
I have developed few libraries for robot framework for my feature testing, for these libraries all variables are coming from a variables.py file. Below is the code block for variables.py:
#!/usr/bin/env python
import sys
import os
import optparse
import HostProperties
import xml.etree.ElementTree as ET
from robot.api import logger
testBed = 748
tree = ET.parse('/home/p6mishra/mybkp/testLibs/TestBedProperties.xml')
class raftGetTestBedProp(object):
def GetTestBedNumber(self):
_attributeDict = {}
root = tree.getroot()
for _tbProperties in root:
for _tbNumber in _tbProperties:
get_tb = _tbNumber.attrib
if get_tb['name']== str(testBed):
get_tb2 = _tbNumber.attrib
return root, get_tb2['name']
def GetTestBedProperties(self, root, testBedNumber):
propertyList = []
for _tbProperties in root:
get_tb = _tbProperties.attrib
for _tbProperty in _tbProperties:
get_tb1 = _tbProperty.attrib
if get_tb1['name']== str(testBedNumber):
for _tbPropertyVal in _tbProperty:
get_tb2 = _tbPropertyVal.attrib
if 'name' in get_tb2.keys():
propertyList.append(get_tb2['name'])
return propertyList
def GetIPNodeType(self, root, testBedNumber):
for tbNumber1 in root.findall('tbproperties'):
for tbNumber in tbNumber1:
ipv4support = tbNumber.find('ipv4support').text
ipv6support = tbNumber.find('ipv6support').text
lbSetup = tbNumber.find('lbSetup').text
name = tbNumber.get('name')
if name==str(testBedNumber):
return ipv4support, ipv6support, lbSetup
obj1, obj2 = raftGetTestBedProp().GetTestBedNumber()
ipv4support, ipv6support, lbSetup = raftGetTestBedProp().GetIPNodeType(obj1, obj2)
AlltestBedProperties = raftGetTestBedProp().GetTestBedProperties(obj1, obj2)
HostPropertyDict = {}
for testBedProperty in AlltestBedProperties:
try:
val1 = getattr(HostProperties, testBedProperty)
HostPropertyDict[testBedProperty] = val1
except:
logger.write("Error in the Configuration data. Please correct and then proceed with the testing", 'ERROR')
for indexVal in range(len(AlltestBedProperties)):
temp = AlltestBedProperties[indexVal]
globals()[temp] = HostPropertyDict[temp]
This variables.py file returns all variables defined in HostProperties.py file based on testbed number.
If i import this library like from variables import * in other libraries it gives me the required variables.
But the problem is here I have hardcoaded 748 so it works fine for me but i want to pass this testbed number information from pybot command and make it available for my Robot testcase as well as all the developed libraries.
Can you post Robot Framework code you use to call these Python files? I think you could use pybot -v testBed:748 and pass it as a parameter to __init__ your class. I am not sure without seeing how you start your Python variables.
A bit different way is to use environment variables:
#!/usr/bin/env python
import sys
import os
import optparse
import HostProperties
import xml.etree.ElementTree as ET
from robot.api import logger
testBed = os.environ['testbed']
tree = ET.parse('/home/p6mishra/mybkp/testLibs/TestBedProperties.xml')
Before starting pybot just define this environment parameter:
export testbed=748
pybot tests.txt
This is my sample program:
#!/usr/bin/python
import os
import string
import argparse
parser = argparse.ArgumentParser(description="get all versions")
parser.add_argument(test-version)
version = parser.parse_args()
print(version.test-version)
When I run the python script, it throws the error:
AttributeError: 'Namespace' object has no attribute 'test'
If I try the same example with argument "test" instead of "test-version" it works fine.
It is important for me to have the - in my argument name.
How can I fix this issue?
Thanks
The issue is that you can't have a - in a variable name, because it's the subtraction operator. So, in your code, the interpreter is trying to do version.test - version, which doesn't work because version doesn't have a .test attribute and you can't subtract a namespace from something. If you want to use - in the argument, you need to set the dest= parameter in .add_argument().
For example:
import argparse
parser = argparse.ArgumentParser(description="get all versions")
parser.add_argument('--test-version', dest='test_version')
version = parser.parse_args(['--test-version', '1'])
print(version.test_version)
or if you want it as a status flag:
import argparse
parser = argparse.ArgumentParser(description="get all versions")
parser.add_argument('--test-version', action='store_true', dest='test_version')
version = parser.parse_args(['--test-version'])
print(version.test_version)
Try this:
print(getattr(version, 'test-version'))
Im trying to import files on Flask app in base of url route. I started to coding python few days ago so i havent idea if i doing it well. I write this on :
#app.route('/<file>')
def call(file):
__import__('controller.'+file)
hello = Example('Hello world')
return hello.msg
And i have other file called example.py into a controller folder that contains this:
class Example:
def __init__(self, msg):
self.msg = msg
So i start from terminal the app and i try to enter to localhost:5000/example.
Im trying to show in screen Hello world but give me the next error:
NameError: global name 'Example' is not defined
Thanks for all!
__import__ returns the newly imported module; names from that module are not added to your globals, so you need to get the Example class as an attribute from the returned module:
module = __import__('controller.'+file)
hello = module.Example('Hello world')
__import__ is rather low-level, you probably want to use importlib.import_module() instead:
import importlib
module = importlib.import_module('controller.'+file)
hello = module.Example('Hello world')
If you need to dynamically get the classname too, use getattr():
class_name = 'Example'
hello_class = getattr(module, class_name)
hello = hello_class('Hello world')
The Werkzeug package (used by Flask) offers a helpful functions here: werkzeug.utils.import_string() imports an object dynamically:
from werkzeug.utils import import_string
object_name = 'controller.{}:Example'.format(file)
hello_class = import_string(object_name)
This encapsulates the above process.
You'll need to be extremely careful with accepting names from web requests and using those as module names. Please do sanitise the file argument and only allow alphanumerics to prevent relative imports from being used.
You could use the werkzeug.utils.find_modules() function to limit the possible values for file here:
from werkzeug.utils import find_modules, import_string
module_name = 'controller.{}'.format(file)
if module_name not in set(find_modules('controller')):
abort(404) # no such module in the controller package
hello_class = import_string(module_name + ':Example')
I think you might not add the directory to the file, add the following code into the previous python program
# Add another directory
import sys
sys.path.insert(0, '/your_directory')
from Example import Example
There are two ways for you to do imports in Python:
import example
e = example.Example('hello world')
or
from example import Example
e = Example('hello world')
With my python application, I have 40 modules (classes) which contain a parser for some text. In my function I only want to instanciate and use a particular module. These are all sorted in the database.
I am at the point now where I know my parser, and have both the python file name and class I want to import and create
However.... How do you actually do this in python?
eg;
file_name = 'lex_parser'
class_name = 'LexParser'
how can I do....
from {file_name} import {class_name}
Parser = {class_name}()
Follow what I mean?
Try this:
file_name = 'lex_parser'
class_name = 'LexParser'
Parser = getattr(__import__(file_name), class_name)
Note that file_name must not contain .py.
This won't work if the module is within a package because __import__ would return the top level package. In that case you can do this:
import sys
file_name = 'parsers.lex_parser'
class_name = 'LexParser'
__import__(file_name)
Parser = getattr(sys.modules[file_name], class_name)
This will work in both cases and is recommeded by the __import__ function documentation.
In both examples Parser is a class which you have to instantiate as normally:
parser = Parser()
How about something like this:
module = __import__('my_module')
if hasattr(module, 'ClassName'):
ClassName = module.ClassName
my_object = ClassName()