How would I separate my Python File to multiple plugins? - python

So first thing I want to say: I have been looking into modules and such, I just don't quiet know how I would rewrite it to fit this in.
Project: What I have is a Skype Bot using the Skype4Py module. I have about 11 commands I noticed the one script is getting a little large.
I'm trying to think about how to link one main.py file to a Plugin Folder, which contains each and every bot function in it's own respectable Python file. It sounds simple an all, except when it comes to how the function is called.
Here is just a basic look at my Skype bot, missing some of the larger functions.
import Skype4Py, random
class SkypeBot():
def __init__(self):
self.skype = Skype4Py.Skype()
if self.skype.Client.IsRunning == False:
self.skype.Client.Start()
self.skype.Attach()
self.results = ['Yes', 'No', 'Maybe', 'Never']
def main(self):
print ' Skype Bot currently running on user: %s' % self.skype.CurrentUserHandle
print "\n\nCommands Called:\n"
while True:
self.skype.OnMessageStatus = self.RunFunction
def RunFunction(self, Message, Status):
if Status == 'SENT' or Status == 'RECEIVED':
cmd = Message.Body.split(' ')[0]
if cmd in self.functions.keys():
self.context = Message
self.caller = self.context.FromHandle
self.functions[cmd](self)
def ping(self):
print " %s : Ping" % self.caller
self.context.Chat.SendMessage('Pong')
def say(self):
try:
response = self.context.Body.split(' ', 1)
if response[1] == "-info":
print " %s : say -info" % self.caller
self.context.Chat.SendMessage("Resends the message entered. \n"
"Usage: !say Hello. \n"
"Example: Bot: Hello.")
else:
say = response[1]
print " %s : Say [%s]" % (self.caller, say)
self.context.Chat.SendMessage(say)
except:
self.context.Chat.SendMessage("Please use -info to properly use the !say command")
def eightball(self):
try:
question = self.context.Body.split(' ', 1)
if question[1] == "-info":
print " %s : 8Ball -info" % self.caller
self.context.Chat.SendMessage("Responds with an answer.\n"
"Usage: !8ball 'Do I have swag?'\n"
"Example: !8Ball Response: 'Yes'")
else:
random.shuffle(self.results)
answer = self.results[3]
print " %s : 8Ball [%s]" % (self.caller, question[1])
self.context.Chat.SendMessage("!8Ball Response: %s" % answer)
except:
self.context.Chat.SendMessage("Please use -info to properly use the !8ball command")
#FUNCTIONS LIST
#********************
functions = {
"!ping": ping,
"!say": say,
"!8ball": eightball,
}
if __name__ == "__main__":
snayer = SkypeBot()
snayer.main()
So basically, what I am wondering, how can I change
self.skype.OnMessageStatus = self.RunFunction
so that it'll run functions from another file?

For a program of this size it's not really necessary to put your command functions into separate files, but I guess it is good organization. And good practice for when you write a program that has thousands of lines of code. :)
One way to do this is to create a basic SkypeBot class without any command methods and then import the command methods from your plugins directory and add them to the class. It's easy enough to add new attributes to an existing class, and it doesn't matter if the new attributes are properties or methods, the syntax to add them is identical. (With a tiny bit more work it's even possible to add new attributes to an instance, so you can have multiple instances, each with their own individual set of commands. But I guess that's not necessary here, since a program that uses the SkypeBot class will normally only create a single instance).
So we can break your question into two parts:
How to add methods to an existing class.
How to import those methods
from other source files.
As I said, 1) is easy. 2) is quite easy as well, but I've never done it before, so I had to do a little bit of research and testing, and I can't promise that what I've done is best practice, but it works. :)
I don't know much about Skype, and I don't have that Skype4Py module, and as you said, the code above is not the complete program, so I've written some fairly simple code to illustrate the process of adding plugin methods from separate files to an existing class.
The name of the main program is "plugin_demo.py". To keep things neat, it lives in its own directory, "plugintest/", which you should create somewhere in your Python path (eg where you normally keep your Python programs). This path must be specified in your PYTHONPATH environment variable.
"plugintest/" has the following structure:
plugintest/
__init__.py
plugin_demo.py
plugins/
__init__.py
add.py
multiply.py
The __init__.py files are used by Python's import machinery to let it know that a directory contains a Python package, see 6.4. Packages in the Python docs for further details.
Here are the contents of those files. Firstly, the files that go into "plugintest/" itself:
__init__.py
__all__ = ['plugin_demo', 'plugins']
from plugintest import *
plugin_demo.py
#! /usr/bin/env python
#A simple class that will get methods added later from plugins directory
class Test(object):
def __init__(self, data):
self.data = data
def add_plugins(cls):
import plugins
print "Adding plugin methods to %s class" % cls.__name__
for name in plugins.__all__:
print name
plug = getattr(plugins, name)
print plug
method = getattr(plug, name)
print method
setattr(cls, name, method)
print
print "Done\n"
add_plugins(Test)
def main():
#Now test it!
t = Test([1, 2, 3]); print t.data
t.multiply(10); print t.data
t.add(5); print t.data
if __name__ == '__main__':
main()
And now the contents of the "plugintest/plugins/" directory:
__init__.py
__all__ = ['add', 'multiply']
from plugintest.plugins import *
add.py
#A method for the Test class of plugin_demo.py
def add(self, m):
self.data = [m + i for i in self.data]
multiply.py
#A method for the Test class of plugin_demo.py
def multiply(self, m):
self.data = [m * i for i in self.data]
If you cd to the directory containing the "plugintest/" folder, you should be able to run it with
python plugintest/plugin_demo.py
and if you cd to "plugintest/" itself
python plugin_demo.py
Also, in the interpreter (or another Python program), you should be able to do
import plugintest
and then run the main() function of "plugin_demo.py" with
plugintest.plugin_demo.main()
The other usual variations of from ... import ... etc should also work as expected.
The function in "plugin_demo.py" that performs the magic of adding the imported methods to the Test class is add_plugins(). When it runs it prints out each method name, its module, and its function. This could be handy during development, but you'd probably comment out some of those print statements once the program's working properly.
I hope this helps, and if you have any questions please don't hesitate to ask.

Related

Mocking os.path.exists and os.makedirs returning AssertionError

I have a function like below.
# in retrieve_data.py
import os
def create_output_csv_file_path_and_name(output_folder='outputs') -> str:
"""
Creates an output folder in the project root if it doesn't already exist.
Then returns the path and name of the output CSV file, which will be used
to write the data.
"""
if not os.path.exists(output_folder):
os.makedirs(output_folder)
logging.info(f"New folder created for output file: " f"{output_folder}")
return os.path.join(output_folder, 'results.csv')
I also created a unit test file like below.
# in test_retrieve_data.py
class OutputCSVFilePathAndNameCreationTest(unittest.TestCase):
#patch('path.to.retrieve_data.os.path.exists')
#patch('path.to.retrieve_data.os.makedirs')
def test_create_output_csv_file_path_and_name_calls_exists_and_makedirs_once_when_output_folder_is_not_created_yet(
self,
os_path_exists_mock,
os_makedirs_mock
):
os_path_exists_mock.return_value = False
retrieve_cradle_profile_details.create_output_csv_file_path_and_name()
os_path_exists_mock.assert_called_once()
os_makedirs_mock.assert_called_once()
But when I run the above unit test, I get the following error.
def assert_called_once(self):
"""assert that the mock was called only once.
"""
if not self.call_count == 1:
msg = ("Expected '%s' to have been called once. Called %s times.%s"
% (self._mock_name or 'mock',
self.call_count,
self._calls_repr()))
raise AssertionError(msg)
AssertionError: Expected 'makedirs' to have been called once. Called 0 times.
I tried poking around with pdb.set_trace() in create_output_csv_file_path_and_name method and I'm sure it is receiving a mocked object for os.path.exists(), but the code never go pasts that os.path.exists(output_folder) check (output_folder was already created in the program folder but I do not use it for unit testing purpose and want to keep it alone). What could I possibly be doing wrong here to mock os.path.exists() and os.makedirs()? Thank you in advance for your answers!
You have the arguments to your test function reversed. When you have stacked decorators, like:
#patch("retrieve_data.os.path.exists")
#patch("retrieve_data.os.makedirs")
def test_create_output_csv_file_path_...():
They apply bottom to top, so you need to write:
#patch("retrieve_data.os.path.exists")
#patch("retrieve_data.os.makedirs")
def test_create_output_csv_file_path_and_name_calls_exists_and_makedirs_once_when_output_folder_is_not_created_yet(
self, os_makedirs_mock, os_path_exists_mock
):
With this change, if I have this in retrieve_data.py:
import os
import logging
def create_output_csv_file_path_and_name(output_folder='outputs') -> str:
"""
Creates an output folder in the project root if it doesn't already exist.
Then returns the path and name of the output CSV file, which will be used
to write the data.
"""
if not os.path.exists(output_folder):
os.makedirs(output_folder)
logging.info(f"New folder created for output file: " f"{output_folder}")
return os.path.join(output_folder, 'results.csv')
And this is test_retrieve_data.py:
import unittest
from unittest.mock import patch
import retrieve_data
class OutputCSVFilePathAndNameCreationTest(unittest.TestCase):
#patch("retrieve_data.os.path.exists")
#patch("retrieve_data.os.makedirs")
def test_create_output_csv_file_path_and_name_calls_exists_and_makedirs_once_when_output_folder_is_not_created_yet(
self, os_makedirs_mock, os_path_exists_mock
):
os_path_exists_mock.return_value = False
retrieve_data.create_output_csv_file_path_and_name()
os_path_exists_mock.assert_called_once()
os_makedirs_mock.assert_called_once()
Then the tests run successfully:
$ python -m unittest -v
test_create_output_csv_file_path_and_name_calls_exists_and_makedirs_once_when_output_folder_is_not_created_yet (test_retrieve_data.OutputCSVFilePathAndNameCreationTest.test_create_output_csv_file_path_and_name_calls_exists_and_makedirs_once_when_output_folder_is_not_created_yet) ... ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Update I wanted to leave a comment on the diagnostics I performed here, because I didn't initially spot the reversed arguments, either, but the problem became immediately apparent when I added a breakpoint() the beginning of the test and printed out the values of the mocks:
(Pdb) p os_path_exists_mock
<MagicMock name='makedirs' id='140113966613456'>
(Pdb) p os_makedirs_mock
<MagicMock name='exists' id='140113966621072'>
The fact that the names were swapped made the underlying problem easy to spot.

How to solve class objecto has no atribute

beginner Python user here.
So, I´m trying to make a program that orders the files of my (many) Downloads folder.
I made a class object to work with the many folders:
class cContenedora:
def __int__(self, nCarp, dCarp): #nCarp Stands is the file name and dCarp Stands for file directory.
self.nCarp = nCarp
self.dCarp = dCarp
So, y wrote a instance like this:
Download = cContenedora()
Download.nCarp = "Downloads/"
#The side bar is for making a path to move my archives from with shutil.move(path, dest)
Download.dCarp = "/Users/MyName/Download/"
#This is for searching the folder with os.listdir(Something.dCarp)
Then, I wrote my function, and it goes something like this:
def ordenador(carpetaContenedora, formato, directorioFinal): #carpetaContenedora is a Download Folder
carpetaContenedora = cContenedora() #carpetaContenedora one of the class objects
dirCCont = os.listdir(carpetaContenedora.dCarp) #The to directory is carpetaContenedora.cCarp
for a in dirCCont:
if a.endswith(formato):
path = "/Users/Aurelio Induni/" + carpetaContenedora().nCarp + a
try:
shutil.move(path, directorioFinal)
print(Fore.GREEN + a + "fue movido exitosamente.")
except:
print(Fore.RED + "Error con el archivo" + a)
pass
for trys in range(len(listaCarpetasDestino)-1): #Is a list full of directories.
for container in listaCarpetasFuente: #A short list of all my Downloads Folder.
for formatx in listaFormatos: #listaFormatos is a list ful of format extensions like ".pdf"
#try: #I disabled this to see the error istead of "Error Total"
ordenador(container, formatx, listaCarpetasDestino[trys])
#except:
#print(Fore.RED + "Error Total") #I disabled this to see the error.
But every time I run it I get the following:
AttributeError: 'cContenedora' object has no attribute 'dCarp'
It says the error is in line 47 (the one with the os.listdir(carpetaContenedora.dCarp))
I´m sure is something small. Python is so amazing, but it also can be so frustrating not knowing what´s wrong.
There is a spelling mistake in the initialization of your instance. It should be "init" instead of "int".
In the class cContenedora, the function should be
class cContenedora:
def __init__(self, nCarp, dCarp):
self.nCarp = nCarp
self.dCarp = dCarp
Additionally, When you are passing in the parameter. Make sure to pass in both of the parameters in the line with Value.
CContenedora(nCarp="something",dCarp="something")
Your class initializer, i.e., __init__() function has 2 parameters nCarp and dCarp but when you are actually creating the object there are no parameters passed.
Your function ordenador takes the first parameter as carpetaContenedora, on the first line same variable is assigned a new object of cContenedora, at this line the original values you passed are lost forever.
This could be the reason it is giving for the error.
Refer this link for more details on how to create classes and instantiate the object.

What's the best way to implement an SCPI command tree structure as Python class methods?

SCPI commands are strings built of mnemonics that are sent to an instrument to modify/retrieve its settings and read measurements. I'd like to be able to build and send a string like this: "SENSe:VOLTage:DC:RANGe 10 V"
With code like this:
inst.sense.voltage.dc.range('10 V')
But it seems like a very deep rabbit hole and I'm not sure I want to start down it. Loads of classes for each subsystem and option....
Would a better approach be something like:
def sense_volt(self, currenttype='DC', RANG='10 V'):
cmdStr = 'SENS:VOLT:' + currenttype + ':RANG: ' + RANG
return self.inst.write(cmdStr)
It's trivial to just implement the commands I need and leave inst.query(arg) and inst.write(arg) methods for manually building additional commands, but I'd like to eventually have a complete instrument interface where all commands are covered by autocompleteable methods.
I managed it, though I'm pretty unhappy with the results. It's been three years since I touched any of this, so I'm not sure why I did some things the way I did. I know I had a lot of trouble wrapping my head around organizing everything for portability. I'm sure that now, after a long wait, I'll be inundated with suggestions for how I should have done it.
I wrote parsing functions to interpret SCPI commands. They can separate the command from the arguments, determine required and optional arguments, recognize queries, etc. For example:
def command_name(scpi_command):
cmd = scpi_command.split(' ')[0]
new = ''
for i, c in enumerate(cmd):
if c in '[]':
continue
if c.isupper() or c.isdigit():
new += c.lower()
continue
if c == ':':
new += '_'
continue
if c == '?':
new += '_qry'
break
return new
The command from CONFigure[:VOLTage]:DC [{<range>|AUTO|MIN|MAX|DEF} [, {<resolution>|MIN|MAX|DEF}]] can be parsed as conf_volt_dc, or conf_dc. I did not use the abridged option in my experiments. I think some of my dissatisfaction stemmed from the extra-long method names.
I wrote a builder script to read the commands from a file, parse them, and write a new script with a "command set" class extending a "command handler." Every command is parsed and converted into one of a few boilerplate methods, such as:
query_str_no_args = r'''
def {name}(self):
"""SCPI instrument query.
{s}
"""
cmd = '{s}'
return self._command_handler(command=cmd)
'''
The parser also includes a command handler class to process commands and arguments. Each command is parsed from its example text, ala >>> _command_handler(0.1, 'MAX', command='CONFigure[:VOLTage]:DC [{<range>|AUTO|MIN|MAX|DEF} [, {<resolution>|MIN|MAX|DEF}]]'. Arguments (if any) are validated, and the command string is rebuilt and sent to the instrument,
class Cmd_Handler():
def _command_handler(self, *args, command):
# command string 'SENS:VOLT:RANG'
cmd_str = command_string(command)
# argument dictionary {0: [True, '<range>, 'AUTO', 'MIN', 'MAX', 'DEF'],
# 1: [False, '<resolution>', 'MIN', 'MAX', 'DEF']}
arg_dict = command_args(command)
if debug_mode: print(arg_dict)
for k, v in arg_dict.items():
for i, j in enumerate(v[1:]):
...
# Validate arguments
# count mandatory arguments
if len(args) < len([arg_dict[k] for k in arg_dict.keys() if arg_dict[k][0]]):
...
if '?' in cmd_str:
return self._query(cmd_str + arg_str)
else:
return self._write(cmd_str + arg_str)
When the builder is done, you end up with a big script (the Ag34401 and Ag34461 files were 2600 and 3600 lines, respectively) that looks like this:
#!/usr/bin/env python3
from scpi.scpi_parse import Cmd_Handler
class Ag34461A_CS(Cmd_Handler):
...
def calc_scal_stat(self, *args):
"""SCPI instrument command.
CALCulate:SCALe[:STATe] {OFF|ON}
"""
cmd = 'CALCulate:SCALe[:STATe] {OFF|ON}'
return self._command_handler(*args, command=cmd)
def calc_scal_stat_qry(self):
"""SCPI instrument query.
CALCulate:SCALe[:STATe]?
"""
cmd = 'CALCulate:SCALe[:STATe]?'
return self._command_handler(command=cmd)
Then you extend this class with your short, sweet instrument class:
#!/usr/bin/env python3
import pyvisa as visa
from scpi.cmd_sets.ag34401a_cs import Ag34401A_CS # Extend the command set
class Ag34401A(Ag34401A_CS):
def __init__(self, resource_name=None):
rm = visa.ResourceManager()
self._inst = None
if resource_name:
inst = rm.open_resource(resource_name)
else:
for resource in rm.list_resources():
inst = rm.open_resource(resource)
if '34401' in inst.query("*IDN?"):
self._inst = inst
break
if not self._inst:
raise visa.errors.VisaIOError
assert isinstance(self._inst, visa.resources.GPIBInstrument)
self._query = self._inst.query
self._write = self._inst.write
I also have a SCPI instrument parent class that I was trying to fill with all of the star commands (*IDN?, *CLS, etc.) I wasn't happy with the previous results and was intimidated by some of the star commands' mounting complexity (some of which seemed really instrument-specific), and abandoned it. Here's the first bit
class SCPI_Instrument(object, metaclass=ABCMeta):
#abstractmethod
def query(self, message, delay):
pass
#abstractmethod
def write(self, message, delay):
pass
# *CLS - Clear Status
def cls(self, termination = None, encoding = None):
"""Clears the instrument status byte by emptying the error queue and clearing all event registers.
Also cancels any preceding *OPC command or query."""
return self.write("*CLS", termination, encoding)
In the end, the documentation I was able to squeeze into it wasn't as helpful as I wanted. The autocomplete wasn't able to prompt for arguments by name, and having every single command suggested was less helpful than I expected. Trying to keep the import paths straight was difficult enough for me, much less someone who might end up using my code.
Ultimately, coding has never been part of my job description, and I was moved to a position where experimenting with instrument control is even less possible.

Sublime Text 3 Plugin changing run to on_pre_save

I have been working on a Sublime Text 3 plugin that fixes some coding standards I have at work(That I have a bad habit of missing) I currently have this working with a command run in the console. Most of the code was originally from this thread.
import sublime, sublime_plugin
class ReplaceCommand(sublime_plugin.TextCommand):
def run(self, edit):
#for each selected region
region = sublime.Region(0, self.view.size())
#if there is slected text
if not region.empty():
#get the selected region
s = self.view.substr(region)
#perform the replacements
s = s.replace('){', ') {')
s = s.replace('}else', '} else')
s = s.replace('else{', 'else {')
#send the updated string back to the selection
self.view.replace(edit, region, s)
Then you just need to run:
view.run_command('replace')
And it will apply the coding standards(there are more I plan to implement but for now i'll stick with these) I would like this to run on save.
I tried just changing run(self, edit) to on_pre_save(self, edit) but it does not work. I don't get any syntax errors but It just doesn't work.
Can anyone tell me how to make this run on save instead of having to run the command?
On ST3 the only way to get an Edit object is by running a TextCommand. (It's in the docs, but they're not terribly clear). But, fortunately, you can run the command pretty much the same way you have been doing.
Events handlers, like on_pre_save, can only be defined on an EventListener. The on_pre_save() event is passed a view object so you just need to add something like this, which kicks-off the command you've already written.
class ReplaceEventListener(sublime_plugin.EventListener):
def on_pre_save(self, view):
view.run_command('replace')
The Solutions I came to was to create an on_pre_save() function that runs the command I listed earlier:
import sublime, sublime_plugin
class ReplaceCodeStandardsCommand(sublime_plugin.TextCommand):
def run(self, edit):
#for each selected region
region = sublime.Region(0, self.view.size())
#if there is slected text
if not region.empty():
#get the selected region
s = self.view.substr(region)
#perform the replacements
s = s.replace('){', ') {')
s = s.replace('}else', '} else')
s = s.replace('else{', 'else {')
#send the updated string back to the selection
self.view.replace(edit, region, s)
class ReplaceCodeStandardsOnSave(sublime_plugin.EventListener):
# Run ST's 'unexpand_tabs' command when saving a file
def on_pre_save(self, view):
if view.settings().get('update_code_standard_on_save') == 1:
view.window().run_command('replace_code_standards')
Hopefully this code helps someone!

Importing a function from a class in another file? [duplicate]

This question already has answers here:
How do I import other Python files?
(23 answers)
Why is Python running my module when I import it, and how do I stop it?
(12 answers)
Closed 6 months ago.
I'm writing a Python program for fun but got stuck trying to import a function from a class in another file. Here is my code:
#jurassic park mainframe
from random import randint
from sys import exit
from comm_system import Comm_system #the file i want to import from
class Jpark_mainframe(object):
def mainframe_home(self):
print "=====Welcome to the Jurassic Park Mainframe====="
print "==========Security Administration==============="
print "===========Communications Systems==============="
print "===============System Settings=================="
print "===================Quit========================="
prompt = raw_input("What would you like to do? ")
while prompt != "Quit":
if prompt == "Security Administration":
print "Please enter the 5-digit passcode:"
security_passcode = "%d%d%d%d%d" % (2, 0, 1, 2, randint(1, 2))
security_guess = raw_input(": ")
security_guesses = 0
while security_guess != security_passcode and security_guesses < 7:
print "Incorrect. Please enter the security passcode."
security_guesses += 1
security_guess = raw_input(": ")
if security_guess == security_passcode:
print "=========Security Administration======="
print "Area 1 Fences: Off"
print "Area 2 Fences: On"
print "Area 3 Fences: Off"
print "Velociraptor Compound: Off"
print "Lobby Security System: Off"
print "Entrance Facility System: Off"
print "To enable all systems, enter 'On'"
enable_security = raw_input(": ")
if enable_security == "On":
print "Systems Online."
if prompt == "System Settings":
print "You do not have access to system settings."
exit(0)
if prompt == "Communications Systems":
print "===========Communications Systems==========="
print "error: 'comm_link' missing in directories"
exit(0)
return Comm_system.run #this is where I want to return the
#the other file
the_game = jpark_mainframe()
the_game.mainframe_home()
I want to return a function called run() from a class in another file. When I import the file, it first runs the class with run() in it, then proceeds to run the original code. Why does this happen?
Here is the code from comm_system:
#communication systems
from sys import exit
class Comm_system(object):
def run(self):
comm_directory = ["net_link", "tsfa_run", "j_link"]
print "When the system rebooted, some files necessary for"
print "communicating with the mainland got lost in the directory."
print "The files were poorly labeled as a result of sloppy"
print "programming on the staff's part. You must locate the"
print "the file and contact the rescue team before the dinosaurs"
print "surround the visitor's center. You were also notified the"
print "generators were shorting out, and the mainframe will lose"
print "power at any moment. Which directory will you search in?"
print "you don't have much time! Option 1: cd /comm_sys/file"
print "Option 2: cd /comm_sys/dis"
print "Option 3: cd /comm_sys/comm"
dir_choice = raw_input("jpark_edwin$ ")
if dir_choice == "/comm_sys/file" or dir_choice == "/comm_sys/dis":
print "misc.txt"
print "You couldn't locate the file!"
print "The system lost power and your computer shut down on you!"
print "You will not be able to reach the mainland until the system"
print "comes back online, and it will be too late by then."
return 'death'
if dir_choice == "/comm_sys/comm":
comm_directory.append("comm_link")
print comm_directory
print "You found the right file and activated it!"
print "Just in time too, because the computers shut down on you."
print "The phonelines are radios are still online."
print "You and the other survivors quickly call the mainlane"
print "and help is on the way. You all run to the roof and wait"
print "until the helocopter picks you up. You win!"
a_game = Comm_system()
a_game.run()
from otherfile import TheClass
theclass = TheClass()
# if you want to return the output of run
return theclass.run()
# if you want to return run itself to be used later
return theclass.run
Change the end of comm system to:
if __name__ == '__main__':
a_game = Comm_system()
a_game.run()
It's those lines being always run that are causing it to be run when imported as well as when executed.
from FOLDER_NAME import FILENAME
from FILENAME import CLASS_NAME FUNCTION_NAME
FILENAME is w/o the suffix
First you need to make sure if both of your files are in the same working directory. Next, you can import the whole file. For example,
import myClass
or you can import the entire class and entire functions from the file. For example,
from myClass import
Finally, you need to create an instance of the class from the original file and call the instance objects.
If, like me, you want to make a function pack or something that people can download then it's very simple. Just write your function in a python file and save it as the name you want IN YOUR PYTHON DIRECTORY. Now, in your script where you want to use this, you type:
from FILE NAME import FUNCTION NAME
Note - the parts in capital letters are where you type the file name and function name.
Now you just use your function however it was meant to be.
Example:
FUNCTION SCRIPT - saved at C:\Python27 as function_choose.py
def choose(a):
from random import randint
b = randint(0, len(a) - 1)
c = a[b]
return(c)
SCRIPT USING FUNCTION - saved wherever
from function_choose import choose
list_a = ["dog", "cat", "chicken"]
print(choose(list_a))
OUTPUT WILL BE DOG, CAT, OR CHICKEN
Hoped this helped, now you can create function packs for download!
--------------------------------This is for Python 2.7-------------------------------------
It would really help if you'd include the code that's not working (from the 'other' file), but I suspect you could do what you want with a healthy dose of the 'eval' function.
For example:
def run():
print "this does nothing"
def chooser():
return "run"
def main():
'''works just like:
run()'''
eval(chooser())()
The chooser returns the name of the function to execute, eval then turns a string into actual code to be executed in-place, and the parentheses finish off the function call.
You can use the below syntax -
from FolderName.FileName import Classname

Categories