How can I reference a variable from another file - python

I have two files: client.py and ItemDatabase.py. I'm trying to store item values in a separate source file, similar to a database, and then call on those item values when I need them in other source files. Here I have the classes Item and WeaponData, which both hold information about the item, and then the instance itself is created in the ItemDatabase. When I want to get that information in the other source file through a print statement I am getting an error: NameError: name 'tinder_sword' is not defined, even though my IDE recognizes that tinder_sword is apart of ItemDatabase.
In client.py:
from ItemDatabase import *
import pygame as pg
class Item:
def __init__(self):
self.name = ""
self.description = ""
self.max_stack_size = 0
self.icon = ""
class WeaponData(Item):
def __init__(self):
super().__init__()
self.damage = 0
self.range = 0
self.cooldown = 0
self.max_condition = 0
self.max_stack_size = 1
print(tinder_sword.name)
In ItemDatabase.py:
from client import *
tinder_sword = WeaponData()
tinder_sword.name = "Tinder Sword"
tinder_sword.description = "Weak and flimsy, but it's not bad for a starter weapon."
tinder_sword.damage = 10
tinder_sword.cooldown = 0.2
tinder_sword.max_condition = 75

Hey! So the issue with your code is not that the variable is not getting imported. The issue is that you are importing client into ItemDatabase.py and then importing ItemDatabase into client.
When you import a python file all the code that is not in a scope gets run. So if you follow the logic:
in client.py
from ItemDatabase import *
so now we run the code in ItemDatabase
from client import *
so now we run the code in client
But now python has already imported ItemDatabase so it skips it.
Now we create the 2 classes in client.py and we run the last line of code:
print(tinder_sword.name)
Except. We have not actually run the code to create tinder_sword yet. Because we are still in the phase of importing client into ItemDatabase.
Importing files needs to flow one way, like a river. If you need two files to use data from each other then you can create a class called Populater in file2. File 1 imports Populator, gives it the values that file 2 needs, and then exits. File 2 never needs to import file 1 but it's populate class will still have file 1's values. This is like sending a power boat up the river to fetch some logs and the driving the boat back down the river to be used there.
This is however not a good way to write programs! It usually means that the way you are thinking about your application is too intertwined and will probably lead to more bugs like this down the line.
The "Nice" way to write a program like this is to do what is called "Separation of concerns". One file focuses on doing one thing only. But doing that one thing well. For example: You might have a SwordBuilder file. It creates amazing swords. Then you might have a storage class. It is focused on storing and reading any items you might have to the filesystem so your games can be saved.
Hope this helps!

trying to help here, usually I would create a config.py file contain classes and stuff as what you have in client.py
then import it in doSomething.py then do the printing in there
import pygame as pg
class Item:
def __init__(self):
self.name = ""
self.description = ""
self.max_stack_size = 0
self.icon = ""
class WeaponData(Item):
def __init__(self):
super().__init__()
self.damage = 0
self.range = 0
self.cooldown = 0
self.max_condition = 0
self.max_stack_size = 1
import client.py
tinder_sword = client.WeaponData()
tinder_sword.name = "Tinder Sword"
tinder_sword.description = "Weak and flimsy, but it's not bad for a starter weapon."
tinder_sword.damage = 10
tinder_sword.cooldown = 0.2
tinder_sword.max_condition = 75
print(tinder_sword.name)

Related

Python unit testing with PyTest, stuck on more advanced testing

I have been using PyTest for some time now to write some simple tests (like the ones you find in tutorials and youtube video's) and I thought now it was time to start writing actual test for our python scripts. The scripts are way more advanced than any shown in tutorials so I am getting a bit stuck. I do not want the entire correct answer, but rather a nudge in the right direction if possible. Here is my issue:
We have a script that reads a .md text file and converts it to a pdf file based on an external template. Part of the script is here below (I removed most of it because I first just want to have 1 running test)
class DocumentationEngine:
def __init__(self, title, subtitle, series, style='TIIStyle_Digital_Aug_2020', templateFile='template.docet', tableOfContents=True, listOfFigures=False, listOfTables=False):
self.title = title
self.subtitle = subtitle
self.series = series
self.style = style
self.template = {}
self.hasTOC = tableOfContents
self.hasLOF = listOfFigures
self.hasLOT = listOfTables
self.loadTemplate(templateFile)
def loadTemplate(self, file='template.docet'):
with open(file, "r") as templatefile:
lines = templatefile.readlines()
key = "dummy"
value = ""
for line in lines:
line = line.strip()
if line.startswith('[') and line.endswith(']'):
self.template[key] = value
key = line[1:-1]
value = ""
else:
value += line + '\n'
def build(self, versions=[], content='', filename='Documenter\\_Autogenerated'):
document = self.template["doc"]
document = document.replace("%%style%%", self.style)
document = document.replace("%%body%%",
self.buildFirstPage() +
self.buildTableOfContents() +
self.buildListOfFigures() +
self.buildListOfTables() +
self.buildVersionTable(versions, filename) +
self.buildContentPages(content=content) +
self.buildLastPage()
)
return document
def buildLastPage(self):
return self.template["last_page"]
I am trying to write a simple unit test for the buildLastPage method and have been stuck for several days now.
I am not sure whether or not I need to mock the template file, use a fixture and/or if I can actually test only that method with all dependencies.
I started with the following:
from doceng import DocumentationEngine
import pytest
class Test:
def test_buildLastPage(self):
build_last_page = DocumentationEngine()
assert build_last_page.template(1) == 1
which gives me an error regarding 3 required arguments. When adding the arguments like this:
from doceng import DocumentationEngine
import pytest
class Test:
def test_buildLastPage(self, title, subtitle, series):
build_last_page = DocumentationEngine()
assert build_last_page.template(1) == 1
which gives me an error that the fixture is not found.
I added a fixture in conftest.py file like this:
import pytest
from doceng import DocumentationEngine
#pytest.fixture
def title(title):
return title("test")
which will get me another error, recursive dependency involving fixture 'title' detected
I'm quite stuck so any nudge in the right direction for a newbie would be highly appreciated
The error of the fixtures is regarding your test function test_buildLastPage. The way you are using it, it only needs the self argument.
A test function in pytest without any decorators always expects to find fixtures, that have the same name as the arguments. You did not define any fixtures and also do not use the arguments in your function. Therefore, you can remove them safely.
The actual error points DocumentationEngine(). The class expect 3 arguments when initializing the object. You set no arguments. Check your __init__ function again to find the proper arguments.

How to access the variables of a class - Python

I have the following code to enable the file browser using blender:
import bpy
import os
from bpy.props import StringProperty
from bpy_extras.io_utils import ImportHelper
from bpy.types import Operator
sel = ''
class OpenBrowser(bpy.types.Operator):
bl_idname = "open.file"
bl_label = "Select Excel File"
bli_description = "Simulation output excel file"
filter_glob: StringProperty(default = '*.xls;*.xlsx',options = {'HIDDEN'})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
#somewhere to remember the address of the file
def execute(self, context):
global sel
sel = self.filepath
#self.selected_file = self.filepath
#display = "filepath= "+self.filepath
#print(display) #Prints to console
#Window>>>Toggle systen console
return {'FINISHED'}
def invoke(self, context, event): # See comments at end [1]
context.window_manager.fileselect_add(self)
global sel
sel = self.filepath
#Open browser, take reference to 'self'
#read the path to selected file,
#put path in declared string type data structure self.filepath
return {'RUNNING_MODAL'}
# Tells Blender to hang on for the slow user input
bpy.utils.register_class(OpenBrowser)
#Tell Blender this exists and should be used
# [1] In this invoke(self, context, event) is being triggered by the below command
#but in your script you create a button or menu item. When it is clicked
# Blender runs invoke() automatically.
#execute(self,context) prints self.filepath as proof it works.. I hope.
bpy.ops.open.file('INVOKE_DEFAULT')
print(sel)
The issue I am facing is that I have declared a global variable sel to which I want to save the filepath selected from the user when running the code. However, when I run the script I see that sel has not changed and it is as it was initialized. Could someone please help me on how to access from the class the self.filepath variable? What am I doing wrong here?
If I understand correctly, you want to store that value for later.
I'm not sure why 'sel' doesn't even update in your case, but I think the more correct way would be to use a property like so:
import bpy
# Assign a custom property to an existing type.
bpy.types.Scene.my_sel_value = bpy.props.StringProperty(name="Sel")
# Set property value.
bpy.context.scene.my_sel_value = "Foo"
# Get property value.
print(bpy.context.scene.my_sel_value)
Properties can be added to all ID types, but for "global" values, bpy.types.scene us ussualy used. Though there can be multiple scenes in one project and they will have separate values. Property values are stored when Blender closes.
If you are making an addon, you can also store your value in Addon Preferences. This value will be the same for all blender projects.

How to modify variables in another python file?

windows 10 - python 3.5.2
Hi, I have the two following python files, and I want to edit the second file's variables using the code in the first python file.
firstfile.py
from X.secondfile import *
def edit():
#editing second file's variables by user input
if Language == 'en-US':
print('language is English-us')
elif Language == 'en-UK':
print('language is English-uk')
secondfile.py
Language = 'en-US'
i can add some variables to it by following code, but how can i edit one ?
with open("secondfile.py","a") as f:
f.write("Language = 'en-US'")
Any ideas how to do that?
You can embed the Language in a class in the second file that has a method to change it.
Module 2
class Language:
def __init__(self):
self.language = 'en-US'
def __str__(self):
return self.language
def change(self, lang):
assert isinstance(lang, str)
self.language = lang
language = Language()
Then import the "language," and change it with the change method.
Module 1
from module2 import language
print(language)
language.change("test")
print(language)
This can be done to edit a variable in another file:
import X.secondfile
X.secondfile.Language = 'en-UK'
However, I have two suggestions:
Don't use import * - it pollutes the namespace with unexpected
names
Don't use such global variables, if they are not constants. Some code will read the value before it is changed and some afterwards. And none will expect it to change.
So, rather than this, create a class in the other file.
class LanguagePreferences(object):
def __init__(self, langcode):
self.langcode = langcode
language_preferences = LanguagePreferences('en-UK')

Understanding flow of execution of Python code

I'm trying to do home assignment connected with python from Data Manipulation at Scale: Systems and Algorithms at Curesra. Generally I have problems with understanding base code which was presented as an example of MapReduce alogorythm. I would be grateful for helping me understand it in 2 places, details below.
I tired to go step by step through code flow of below two files after running command:
python wordcount.py 'data/books.json'
File wordcount.py is opened
mr = MapReduce.MapReduce() - me object is created
def __init__(self): part from MapReduce.py is
executed
We come back to wordcount.py
Functions def mapper(record): and def reducer(key,list_of_values): are created but for the time being without execution
Python go to if __name__ == '__main__':
` inputdata = open(sys.argv[1]) - json file is assigned to a
variable
mr.execute(inputdata, mapper, reducer) - A call to the function from MapReduce.py.
And here is my first question we haven't deffined mapper or reducer variable/object so far. Is it just null/no value passed to this function or we somehow defined this variable before but I missed this?
Later me move to def execute(self, data, mapper, reducer): in
MapReduce.py
And there we have mapper(record).
So this is reference to a function in wordcount.py, am I right? But if we have reference to a function in different file shouldn't we use import at the beginning of the file and define from which file this function came?
(...) further code execution
wordcount.py file:
import MapReduce
import sys
"""
Word Count Example in the Simple Python MapReduce Framework
"""
mr = MapReduce.MapReduce()
# =============================
# Do not modify above this line
def mapper(record):
# key: document identifier
# value: document contents
key = record[0]
value = record[1]
words = value.split()
for w in words:
mr.emit_intermediate(w, 1)
def reducer(key, list_of_values):
# key: word
# value: list of occurrence counts
total = 0
for v in list_of_values:
total += v
mr.emit((key, total))
# Do not modify below this line
# =============================
if __name__ == '__main__':
inputdata = open(sys.argv[1])
mr.execute(inputdata, mapper, reducer)
MapReduce.py file:
import json
class MapReduce:
def __init__(self):
self.intermediate = {}
self.result = []
def emit_intermediate(self, key, value):
self.intermediate.setdefault(key, [])
self.intermediate[key].append(value)
def emit(self, value):
self.result.append(value)
def execute(self, data, mapper, reducer):
for line in data:
record = json.loads(line)
mapper(record)
for key in self.intermediate:
reducer(key, self.intermediate[key])
#jenc = json.JSONEncoder(encoding='latin-1')
jenc = json.JSONEncoder()
for item in self.result:
print jenc.encode(item)
Thank you in advance for help with that.
In python everything is a object, that include functions, so you can pass a functionA as argument to another functionB (or class or whenever), and if functionB expect that you to do it, it will assume that you give it a functions with the right firm and a proceed as normal.
In yours case
mr.execute(inputdata, mapper, reducer)
here mapper, reducer are the functions previously defined that are passed as argument to the method execute of the instance mr of the class MapReduce and as you can see, said method use it as the functions that it expect.
Thank to this you can, as the that code show, make generic code that do some calculus that can be used in similar way by many applications by given the user the options of supplies his/her own functions.
A much more generic example of this is the function map, this function receive a function that do something, map don't care what it does or where it comefrom, only that receive as many argument as map himself receive (others that say functions) and return a value to build a new list with the results.

AttributeError: 'module' object has no attribute 'newperson'

I am currently learning python programming (and am a beginner at it). Currently I am stuck on files exercises (so these are set things I need to do, rather than doing whatever I want. Unfortunately, it also means I probably can't do any complicated (for me) shortcuts)
Currently using Python 3.2.2
I need two different programs. One is to input what the user types in (a name and a DOB) and put that into records in a list and write that into a binary file. The other is to read that file and print that into a table using padding.
Codes:
First
import pickle
class newperson():
def __init__(self):
self.name = ""
self.dob = ""
stop = False
people = []
print("When you want to stop just hit enter")
count = 0
while stop == False:
name = input("Please Enter the name: ")
if len(name) == 0:
stop = True
else:
people.append(newperson())
people[count].name = name
people[count].dob = input("Please enter their DOB: ")
count = count + 1
file = open("ex9.4.dat", "wb")
pickle.dump(people,file)
file.close()
Second:
import pickle
myfile = open("ex9.4.dat", "rb")
people = pickle.load(myfile)
print("{0:<15}{1}".format("Name","DOB"))
for item in people:
print("{0:<15}{1}".format(item.name,item.dob))
The problem is that I am getting the following error when trying to run the 2nd program:
AttributeError: 'module' object has no attribute 'newperson'
on
people = pickle.load(myfile)
Unfortunately, when I have looked for answers on the other questions, either none of the solutions have worked, don't apply to me or mostly just went WAAAY over my head.
What am I doing wrong?
Thanks in advance for the help.
When pickle loads the file it tries to creates newperson instances, but newpersonis not defined in the second program. To solve that problem, you could create a new file newperson.py just containing the definition of the class `newperson.py``
# newperson.py
class newperson():
def __init__(self):
self.name = ""
self.dob = ""
In both programs, import the class after the import or pickle:
from newperson import newperson
Alternatively, you could use a dictionary instead of the newperson class.
I think to unpickle (i.e. pickle.load) you have to have to class newperson somewhere in namespace. try importing class newperson into the module where you run pickle.load.

Categories

Resources