Python - Additional "members" appended to JSON object when passing it to function - python

I have the following JSON object located in its own file called build.json:
{
"name": "utils",
"version": "1.0.0",
"includes": [],
"libraries": [],
"testLibraries": []
}
I obtain this object in my Python program using the following method:
def getPackage(packageName):
jsonFilePath = os.path.join(SRCDIR, packageName, "build.json")
packageJson = None
try:
with open(jsonFilePath, "r") as jsonFile:
packageJson = json.load(jsonFile)
except:
return None
return packageJson
I verify that the JSON object for the current package (which is one of many packages I am iterating over) did not come back None in the following method. Note that I am temporarily printing out the keys of the dictionary:
def compileAllPackages():
global COMPILED_PACKAGES
for packageName in os.listdir(SRCDIR):
package = getPackage(packageName)
if package == None:
continue
# TEMP ==============
for i in package:
print(i)
# ===================
compiledSuccessfully = compilePackage(package)
if not compiledSuccessfully:
return False
return True
Lastly, I am currently also printing out the keys of the dictionary once it is received in the compilePackage function:
def compilePackage(package):
global COMPILED_PACKAGES, INCLUDE_TESTS
# TEMP ==============
for i in package:
print(i)
# ===================
...
Output from compileAllPackages function:
name
version
includes
libraries
testLibraries
Output from compilePackage function:
name
version
includes
libraries
testLibraries
u
t
i
l
s
I can not for the life of me figure out what is happening to my dictionary during that function call??? Please note that the build.json file is located within a directory named "utils".
Edit:
The Python script is located separate from the build.json file and works on absolute paths. It should also be noted that after getting that strange output, I also get the following exception when trying to access a valid key later (it seems to think the dictionary is a string?...):
Traceback (most recent call last):
File "/Users/nate/bin/BuildTool/unix/build.py", line 493, in <module>
main()
File "/Users/nate/bin/BuildTool/unix/build.py", line 481, in main
compiledSuccessfully = compileAllPackages()
File "/Users/nate/bin/BuildTool/unix/build.py", line 263, in compileAllPackages
compiledSuccessfully = compilePackage(package)
File "/Users/nate/bin/BuildTool/unix/build.py", line 287, in compilePackage
compiledSuccessfully = compilePackage(include)
File "/Users/nate/bin/BuildTool/unix/build.py", line 279, in compilePackage
includes = getPackageIncludes(package)
File "/Users/nate/bin/BuildTool/unix/build.py", line 194, in getPackageIncludes
includes = [package["name"]] # A package always includes itself
TypeError: string indices must be integers
Edit: If I change the parameter name to something other than 'package', I no longer get that weird output or an exception later on. This is not necessarily a fix, however, as I do not know what could be wrong with the name 'package'. There are no globals named as such either.

The answer ended up being very stupid. compilePackage() has the possibility of being called recursively, due to any dependencies the package may rely on. In recursive calls to the function, I was passing a string to the function rather than a dictionary.

I tried your code and the result is like this
Output from compileAllPackages function:
name
version
includes
libraries
testLibraries
Output from compilePackage function:
name
version
includes
libraries
testLibraries
My directory structure is like this
├── test.py
└── tt
└── cc
└── utils
└── build.json
I think your code is correct, it should be that the path parameter you passed is incorrect.

Related

Python get line number of classes from imported module

I have been using importlib to get the module from an imported python file and would like to get the line number where each class is defined in the python file.
For example I have something like this:
testSpec = importlib.util.spec_from_file_location("", old_file)
testModule = importlib.util.module_from_spec(testSpec)
testSpec.loader.exec_module(testModule)
Where old_file is a python file (lets call it old.py). Then using the inspect library I can find all of the classes from old.py in this way:
for name, obj in inspect.getmembers(testModule):
if inspect.isclass(obj):
print(name)
This gives me all of the created class names from old.py which is correct. However, what I would like to do is also get the line number where this class appears in old.py. I have tried to add this line in the if statement right after the print statement: print(inspect.getsourcelines(obj))
However, this errors out in this way:
File "old.py", line 665, in getfile
raise TypeError('{!r} is a built-in class'.format(object))
TypeError: <class '.exampleClassName'> is a built-in class
I am not sure why it considers this user-created class a built-in class, but is there another way that I can just get the line number where this class is defined in old.py? For example if old.py looks like this:
#test comment line 1
#test comment line 2
class exampleClassName:
test = 0
Then when I have the class object exampleClassName I would expect to print out 4 from inspect.getsourcelines(obj) since it is defined on line 4.
An option would be to loop through the file with open and .readline(), and see where the line matches class, then save the line (count) number and class name into a dict.

Don't understand this ConfigParser.InterpolationSyntaxError

So I have tried to write a small config file for my script, which should specify an IP address, a port and a URL which should be created via interpolation using the former two variables. My config.ini looks like this:
[Client]
recv_url : http://%(recv_host):%(recv_port)/rpm_list/api/
recv_host = 172.28.128.5
recv_port = 5000
column_list = Name,Version,Build_Date,Host,Release,Architecture,Install_Date,Group,Size,License,Signature,Source_RPM,Build_Host,Relocations,Packager,Vendor,URL,Summary
In my script I parse this config file as follows:
config = SafeConfigParser()
config.read('config.ini')
column_list = config.get('Client', 'column_list').split(',')
URL = config.get('Client', 'recv_url')
If I run my script, this results in:
Traceback (most recent call last):
File "server_side_agent.py", line 56, in <module>
URL = config.get('Client', 'recv_url')
File "/usr/lib64/python2.7/ConfigParser.py", line 623, in get
return self._interpolate(section, option, value, d)
File "/usr/lib64/python2.7/ConfigParser.py", line 691, in _interpolate
self._interpolate_some(option, L, rawval, section, vars, 1)
File "/usr/lib64/python2.7/ConfigParser.py", line 716, in _interpolate_some
"bad interpolation variable reference %r" % rest)
ConfigParser.InterpolationSyntaxError: bad interpolation variable reference '%(recv_host):%(recv_port)/rpm_list/api/'
I have tried debugging, which resulted in giving me one more line of error code:
...
ConfigParser.InterpolationSyntaxError: bad interpolation variable reference '%(recv_host):%(recv_port)/rpm_list/api/'
Exception AttributeError: "'NoneType' object has no attribute 'path'" in <function _remove at 0x7fc4d32c46e0> ignored
Here I am stuck. I don't know where this _remove function is supposed to be... I tried searching for what the message is supposed to tell me, but quite frankly I have no idea. So...
Is there something wrong with my code?
What does '< function _remove at ... >' mean?
There was indeed a mistake in my config.ini file. I did not regard the s at the end of %(...)s as a necessary syntax element. I suppose it refers to "string" but I couldn't really confirm this.
My .ini file for starting the Python Pyramid server had a similar problem.
And to use the variable from the .env file, I needed to add the following: %%(VARIEBLE_FOR_EXAMPLE)s
But I got other problems, and I solved them with this: How can I use a system environment variable inside a pyramid ini file?

How do I use python-WikEdDiff?

I recently installed python-WikEdDiff package to my system. I understand it is a python extension of the original JavaScript WikEdDiff tool. I tried to use it but I couldn't find any documentation for it. I am stuck at using WikEdDiff.diff(). I wish to use the other functions of this class, such as getFragments() and others, but on checking, it shows the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.4/dist-packages/WikEdDiff/diff.py", line 1123, in detectBlocks
self.getSameBlocks()
File "/usr/local/lib/python3.4/dist-packages/WikEdDiff/diff.py", line 1211, in getSameBlocks
while j is not None and self.oldText.tokens[j].link is None:
IndexError: list index out of range
On checking, I found out that the tokens[] structure in the object remains empty whereas it should have been initialized.
Is there an initialize function that I need to call apart from the default constructor? Or is it something to do with the `WikEdDiffConfig' config structure I passed to the constructor?
You get this error because the WikEdDiff object was cleared internally inside diff(), as shown in this section of the code:
def diff( self, oldString, newString ):
...
# Free memory
self.newText.tokens.clear()
self.oldText.tokens.clear()
# Assemble blocks into fragment table
fragments = self.getDiffFragments()
# Free memory
self.blocks.clear()
self.groups.clear()
self.sections.clear()
...
return fragments
If you just need the fragments, use the returned variable of diff() like this:
import WikEdDiff as WED
config=WED.WikEdDiffConfig()
w = WED.WikEdDiff(config)
f = w.diff("abc", "efg")
# do whatever you want with f, but don't use w
print(' '.join([i.text+i.type for i in f]))
# outputs '{ [ (> abc- ) abc< efg+ ] }'

with open() throwing errors on a json file

So I'm super new to coding and I wanted to design a text based RPG as sort of a fun way to learn some stuff and I picked out the language Python because it was named after Monty Python. How perfect right? Well, that is what I thought until trying to get rooms to load.
I am using json files to store my room names, descriptions, and exits then trying to call them in python via a method I saw on YouTube, here is the code:
def getRoom(id):
ret = None
with open(str(id)+".json", "r") as f:
jsontext = f.read()
d = json.loads(jsontext)
d['id'] = id
ret = Room(**d)
This threw an IOError directory or file not found, so I added a try statement like so:
def getRoom(id):
ret = None
try:
with open(str(id)+".json", "r") as f:
jsontext = f.read()
d = json.loads(jsontext)
d['id'] = id
ret = Room(**d)
except IOError:
print("An error occured")
However now I am getting an "AttributeError: 'NoneType' object has no attribute 'name'" off my look command which I have coded like so:
def look(player, args):
print(player.loc.name)
print("")
print (player.loc.description)
In case this matters here is my json file that I have named 1.json:
{
"name": "A Small Bedroom",
"description": "The old bed room has probably seen many people over the years as the inn sits along a major trade route. The floor boards show wear and creak as you walk over them.",
"neighbors": {"w":2}
}
EDIT:
Full traceback:
Traceback (most recent call last):
File "game.py", line 79, in <module>
main(player) File "game.py", line 68, in main
player.loc = getRoom(1)
File "/home/illyduss/Urth/Locations/room.py", line 6, in getRoom
with open(str(id)+".json", "r") as f:
IOError: [Errno 2] No such file or directory: '1.json'
The error clearly says that the file is not to be found. Try the following.
1. make sure that the filename 1.json is available from where you are calling the python interpretor.
for example: if you are calling $ python game/game.py, then the file should be in the present working directory, not in game dir
Try using absolute paths if you can
import os
base_dir = /path/to/json/dir
filename = str(id)+".json"
abs_file = os.path.join(base_dir, filename)
with open(abs_file, "r"):
#do stuff
If you need the json files to be relative to the game.py file and still need the game file to be called from elsewhere, a good practice would be to define base_dir using __file__ attribute of the python file
base_dir = os.path.dirname(__file__)
The reason you're geting NoneType error is that somehow the loc variable is being set to None. which means that you are passing None to the Player's constructor. Since you haven't provided the code where you initialize player, I am assuming that you're passing the result of getRoom() as loc to the constructor. If that is the case, make sure that the value returned by getRoom is not None. you need an explicit return statement at the end of the function. return ret . by default any function without a return statement returns None. That could be your issue

Write dictionary of lists to xls in Python

1.5 month with Python. I am using Python 3.3.2 with WinPython http://code.google.com/p/winpython/ and port xlwt to Python 3 from here https://github.com/hansrwl/xlwt/tree/py3
This is dict with values as lists. It writes to xls file correctly with the following function.
sampleData = {'Books': ['Book_A', 'Book_B', 'Book_C'],
'Author': ['Author_A', 'Author_B', 'Author_C'],
'Price': ['Price_A', 'Price_B', 'Price_C']}
function:
def saveDataToNewFile(fileName, sheetName, data):
# Creating new workbook
wb = xlwt.Workbook()
# Creating new worksheet with the name specified
ws = wb.add_sheet(sheetName)
# Use dictionary keys as first row values(e.g. headers)
for colIdx, headerCaption in enumerate(data):
ws.write(0, colIdx, headerCaption)
# Use dict values as row values for corresponding columns
for rowIdx, itemVal in enumerate(data[headerCaption]):
ws.write(rowIdx + 1, colIdx, itemVal)
wb.save(fileName)
saveDataToNewFile('sample.xls', 'FirstSaveToXlsSample', sampleData)
- this saved correctly and opened with MS Excel.
I have the same data structure which is produced by this loop:
soup3 = defaultdict(list)
def init_fields(links_first_lvl):
for link in links_first_lvl[1:7]:
soup3['Дата'].append(BeautifulSoup(urllib.request.urlopen(link).read()).select('.author_data'))
soup3['Адрес'].append(link)
return soup3
Here is the structure, dictionary with lists as values (i use pprint to print in console beauty)
PPRINT:
{'url': [ 'http://www.ros.ru/article.php?chapter=1&id=20132503',
'http://www.ros.ru/article.php?chapter=1&id=20132411'],
'date': [[<div class="author_data"><b>Марта Моисеева
</b> № 30 (973) от 24.07.2013
<span class="rubr"> ВЛАСТЬ
</span></div>],
[<div class="author_data"><b>Ольга Космынина
</b> № 29 (972) от 17.07.2013
<span class="rubr"> ВЛАСТЬ
</span></div>]]
saveDataToNewFile('sample2.xls', 'FirstSaveToXlsSample', soup3)
The problem: if i try to save to xls i get an error:
.....
if isinstance(data, basestring):
NameError: global name 'basestring' is not defined
Edit: this is full error stack in console Pycharm
Traceback (most recent call last):
File "F:/Python/NLTK packages/parse_html_py3.3.2.py", line 91, in <module>
saveDataToNewFile('sample2.xls', 'FirstSaveToXlsSample', soup3)
File "F:/Python/NLTK packages/parse_html_py3.3.2.py", line 87, in saveDataToNewFile
ws.write(rowIdx + 1, colIdx, itemVal)
File "F:\WinPython-32bit-3.3.2.0\python-3.3.2\lib\site-packages\xlwt\Worksheet.py", line 1032, in write
self.row(r).write(c, label, style)
File "F:\WinPython-32bit-3.3.2.0\python-3.3.2\lib\site-packages\xlwt\Row.py", line 259, in write
self.__rich_text_helper(col, label, style, style_index)
File "F:\WinPython-32bit-3.3.2.0\python-3.3.2\lib\site-packages\xlwt\Row.py", line 276, in __rich_text_helper
if isinstance(data, basestring):
NameError: global name 'basestring' is not defined
I don't know why, it should work because the structure is the same.
The library you're using is written to work on python 2.x only. Download latest python 2.x from here and try again.
Much lower overhead with LibreOffice. Open the LibreOffice install folder, and scrounge your UNO references from all of the current examples there. Save as XLS. Done.
As the comments suggest, the problem is you are using code that is still written for Python 2, however, before you downgrade to Python 2 as nosklo suggests, make sure you installed the xlwt from the Python 3 branch. After you cloned the xlwt repository, did you remember to perform
git checkout -b py3 origin/py3
before you performed your installation?
If you remembered and you still get the basestring error, then the py3 branch is still incomplete, and you will need to downgrade to Python 2 to run the code in master branch.
You may try changing 'basestring' to 'str'
if isinstance(data, basestring):
NameError: global name 'basestring' is not defined
Probably the object has not such attribute and your test fails, since it just test if the object type is an instance or not, and it implies that your attribute or object already exists.
I recommend you to perform a prior test to verify if the attribute or object exists such as hasattr() or if you consider to use self you can read self.__dict__ to find the existing attributes.

Categories