Reputation: 101
I have been working on a Python Role-Playing game and I have a function to import item data from a text file. The text file is structured as follows:
WEAPON 3 sword_of_eventual_obsolescence 6 10 2 0 10
WEAPON 4 dagger_of_bluntness 2 5 3 1 0
WEAPON 5 sword_of_extreme_flimsiness 3 8 3 7 0
The data importing goes like this:
def items_get():
import os
global items
items = {
"weapon":{},
"armour":{},
"potion":{},
"misc":{}
}
file_dir = ( os.getcwd() + '\Code\items.txt' )
file_in = open( file_dir, 'r')
for each_line in file_in:
line = file_in.readline()
line = line.split(' ')
if line[0] == "WEAPON":
weapon_id = line[1]
name = line[2]
attack_min = line[3]
attack_max = line[4]
range = line[5]
weight = line[6]
value = line[7]
weapon_data = {
"name": name.replace('_', ' '),
"atk_min": attack_min,
"atk_max": attack_max,
"rng": range,
"wt": weight,
"val": value,
}
items["weapon"][weapon_id] = {}
items["weapon"][weapon_id].update(weapon_data)
However, when I print items["weapon"], I get this:
{'4': {'wt': '1', 'atk_min': '2', 'atk_max': '5', 'val': '0', 'name': 'dagger of bluntness', 'rng': '3'}}
As you can see, there is only 1 item there. On other occasions I have had two even though I actually have 3 items listed. Why is this happening, and how do I get all 3 items in the dictionary?
Thanks! :P
EDIT: Here is the data for the potions, in case you were wondering.
elif line.split()[0] == "POTION":
_, id, name, hp_bonus, atk_bonus, range_bonus, ac_bonus, str_bonus, con_bonus, dex_bonus, int_bonus, wis_bonus, cha_bonus, wt, val = line.split()
A healing potion looks like this in the file:
POTION 1 potion_of_healing 20 0 0 0 0 0 0 0 0 0 0.1 2
Upvotes: 0
Views: 58
Reputation: 8740
@noname1014, I know you know this but I want to point out few of the problems with your code (that may occur in some special cases, e.g if you change your file name items.txt
to new_items.txt
, rare_fruits.txt
etc.) and some suggestions.
Do not use
\
as path separators in Windows. Use\\
otherwise you may get into problems.\Code\time_items.txt
will be evaluated as\Code imeitems.txt
because\t
is TAB here.Using
\
only works in few cases if\
followed by any characterA
,p
,n
,t
,"
,'
etc. does not construct escape sequences like\n
,\t
,\f
,\r
,\b
etc.
Have a look at the below example for clarification.
>>> import os
>>>
>>> print(os.getcwd() + '\Code\timeitems.txt')
E:\Users\Rishikesh\Python3\Practice\Code imeitems.txt
>>>
>>> print(os.getcwd() + '\Code\\timeitems.txt')
E:\Users\Rishikesh\Python3\Practice\Code\timeitems.txt
>>>
>>> print(os.getcwd() + '\Code\newitems.txt')
E:\Users\Rishikesh\Python3\Practice\Code
ewitems.txt
>>>
>>> print(os.getcwd() + '\\Code\\newitems.txt')
E:\Users\Rishikesh\Python3\Practice\Code\newitems.txt
>>>
>>> # Do not use it as it may work only in some cases if \ followed by any character does not construct escape sequences.
...
>>> os.getcwd() + '\Code\items.txt'
'E:\\Users\\Rishikesh\\Python3\\Practice\\Code\\items.txt'
>>>
>>> # Use \\ as path separators
...
>>> os.getcwd() + '\\Code\\items.txt'
'E:\\Users\\Rishikesh\\Python3\\Practice\\Code\\items.txt'
>>>
>>> print(os.getcwd() + '\Code\items.txt')
E:\Users\Rishikesh\Python3\Practice\Code\items.txt
>>>
>>> print(os.getcwd() + '\\Code\\items.txt')
E:\Users\Rishikesh\Python3\Practice\Code\items.txt
>>>
If your dictionay is huge and you are facing any issue while looking into its items, pretty it using json module, it has a function called
dumps()
which is used to pretty printlist
anddictionary
objects.It is ok to place
import
statements inside function but placing it on the top is a Pythonic way (https://www.python.org/dev/peps/pep-0008/#imports). It is good for large applications with multiple functions in the same module.Use with statement for opening files, in this case you do not need to close files.
Your code is fine, I have just modified it as below.
import os
global items
import json
def items_get():
items = {
"weapon":{},
"armour":{},
"potion":{},
"misc":{}
}
# Do not use \ as path separators in Windows. Use \\ (\t, \n, \' have speacial meanings)
file_dir = ( os.getcwd() + '\\Code\\items.txt' )
with open( file_dir, 'r') as file_in:
lines = file_in.readlines();
# ['WEAPON 3 sword_of_eventual_obsolescence 6 10 2 0 10\n', 'WEAPON 4 dagger_of_bluntness 2 5 3 1 0\n', 'WEAPON 5 sword_of_extreme_flimsiness 3 8 3 7 0']
for each_line in lines:
# Use strip() to remove any leading/trailing whitespaces (\n, \t, spaces etc.)
line = each_line.strip().split(' ');
if line[0] == "WEAPON":
weapon_id = line[1]
name = line[2]
attack_min = line[3]
attack_max = line[4]
range = line[5]
weight = line[6]
value = line[7]
weapon_data = {
"name": name.replace('_', ' '),
"atk_min": attack_min,
"atk_max": attack_max,
"rng": range,
"wt": weight,
"val": value,
}
items["weapon"][weapon_id] = {}
items["weapon"][weapon_id].update(weapon_data)
return items
# Calling items_get() to get dictionary
items = items_get();
# Pretty printing dictionary using json.dumps()
print(json.dumps(items, indent=4))
» Output
{
"weapon": {
"3": {
"name": "sword of eventual obsolescence",
"atk_min": "6",
"atk_max": "10",
"rng": "2",
"wt": "0",
"val": "10"
},
"4": {
"name": "dagger of bluntness",
"atk_min": "2",
"atk_max": "5",
"rng": "3",
"wt": "1",
"val": "0"
},
"5": {
"name": "sword of extreme flimsiness",
"atk_min": "3",
"atk_max": "8",
"rng": "3",
"wt": "7",
"val": "0"
}
},
"armour": {},
"potion": {},
"misc": {}
}
Upvotes: 0
Reputation:
for each_line in file_in:
line = file_in.readline()
each_line
already contains the next line, because iterating through a file-like object (say, with a for loop) causes it to go by lines.
On each iteration of the loop, the file pointer is advanced by one line (file-like objects, though rewindable, keep track of their last-accessed position), and then before anything is done it gets advanced once more by the readline()
, so the only line that doesn't get skipped entirely is the middle one (4).
To fix this, use the loop variable (each_line
) within the loop body directly and nix the file_in.readline()
.
Upvotes: 2