I am making a project where I need several modules which are imported into one main module. I have decided to move the interaction to a single Tkinter window. Instead of using input() I use tkinter.Entry(), for example. I have functions for each step of the interaction.
When I get past the last function of the first module, the configured button has a command to go to a function in the second module. I get an error saying that the command is not defined.
I seem unable to import the configured button variable into the next module, and anything else I tried gave no result. It simply doesn't go to the next module after the first module is done.
I have made the main Tkinter window in the main module and have it that it will mainloop after importing the other modules. Shouldn't the function I want to call upon be defined? How can I get from one function to the next if the latter is in a separate module?
Here is a minimal example:
main_script.py
import tkinter
mainwindow = tkinter.Tk()
# here i set the window to a certain size etc.
import mod1
import mod2
mainwindow.mainloop()
mod1.py
import tkinter
def button1():
label.destroy()
button1.destroy()
button2.config(text = "continue", command = func2)
def button2():
label.destroy()
button1.destroy()
button2.config(text = "continue", command = func2)
label = tkinter.Label(text = "example label")
button1 = tkinter.Button(text = "button1", command = button1)
button2 = tkinter.Button(text = "button2", command = button2)
label.pack()
button1.pack()
button2.pack()
mod2.py
def func2():
button2.destroy()
print ("haha it works...")
Importing a module has no effect on what the module you import can see. If you want to use mod1 contents in mod2 and mod2 contents in mod1, you need to have them import each other and refer to each other's contents with the appropriate module:
# mod1
import mod2
...
button2.config(text = "continue", command = mod2.func2)
# mod2
import mod1
def func2():
mod1.button2.destroy()
Circular imports cause nasty initialization order issues, though, so imports like this are a bad idea. When dividing your code into modules, try to do so in such a way that import loops like this aren't necessary.
Related
I have a custom gym environment where I am implementing action masking. The code below works well
from toyEnv_mask import PortfolioEnv # file with my custom gym environment
from sb3_contrib import MaskablePPO
from sb3_contrib.common.wrappers import ActionMasker
from stable_baselines3.common.vec_env import DummyVecEnv
from stable_baselines3.common.env_util import make_vec_env
from sb3_contrib.common.maskable.utils import get_action_masks
env = PortfolioEnv()
env = ActionMasker(env,action_mask_fn=PortfolioEnv.action_masks)
env = DummyVecEnv([lambda: env])
model = MaskablePPO("MlpPolicy", env, gamma=0.4, verbose=1, tensorboard_log="./MPPO_tensorboard/")
...
i want to parallelize this and I am trying to use the make_vec_env() class. This sets up ok and starts running, but it does not respect the action masks anymore. This is the line i am using to replace the 3 lines above where i initialize the env.
env = make_vec_env(PortfolioEnv, wrapper_class=ActionMasker,wrapper_kwargs={'action_mask_fn':PortfolioEnv.action_masks} ,n_envs=2)
Any suggestions / help would be greatly appreciated.
i was making it unnecessarily complicated.
a simple env = make_vec_env(PortfolioEnv,n_envs=16) works
and the 3 lines that were working previously could have been just
env = PortfolioEnv()
env = DummyVecEnv([lambda: env])
I have run the code as part of exception handling in python, during a session on Plural-sight but now even if a write a incorrect code the result is OK.
For example : hello world without print statement gives me exit code 0
Could you please advice on it?
code :
try:
import msvcrt
def getkey():
return msvcrt.getch()
except ImportError:
import sys
import tty
import termios
def getkey():
fd=sys.stdin.fileno()
original_attributes =termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, original_attributes)
return ch
You need to make sure that the indentation of your code is correct first.
For example get_key function should be defined in both: the try case and in the catch, in the catch case you indented it correctly under the catch statement, but for the try case you made it on the same level of indentation as the try itself, for the interpreter it means that the function definition is not related to the try you wrote, therefore it throws an error as you should not add code after between the try and catch statement.
a rewrite of your program
try:
import msvcrt
def getkey():
return msvcrt.getch()
except ImportError:
import sys
import tty
import termios
def getkey():
fd=sys.stdin.fileno()
original_attributes =termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, original_attributes)
return ch
This code says now, if we tried to import the library msvcrt and succeeded, then we will define a function get_key using the library, if failed; then we will define it again without using the library.
I have created a custom environment, as per the OpenAI Gym framework; containing step, reset, action, and reward functions. I aim to run OpenAI baselines on this custom environment. But prior to this, the environment has to be registered on OpenAI gym. I would like to know how the custom environment could be registered on OpenAI gym? Also, Should I be modifying the OpenAI baseline codes to incorporate this?
You do not need to modify baselines repo.
Here is a minimal example. Say you have myenv.py, with all the needed functions (step, reset, ...). The name of the class environment is MyEnv, and you want to add it to the classic_control folder. You have to
Place myenv.py file in gym/gym/envs/classic_control
Add to __init__.py (located in the same folder)
from gym.envs.classic_control.myenv import MyEnv
Register the environment in gym/gym/envs/__init__.py by adding
gym.envs.register(
id='MyEnv-v0',
entry_point='gym.envs.classic_control:MyEnv',
max_episode_steps=1000,
)
At registration, you can also add reward_threshold and kwargs (if your class takes some arguments).
You can also directly register the environment in the script you will run (TRPO, PPO, or whatever) instead of doing it in gym/gym/envs/__init__.py.
EDIT
This is a minimal example to create the LQR environment.
Save the code below in lqr_env.py and place it in the classic_control folder of gym.
import gym
from gym import spaces
from gym.utils import seeding
import numpy as np
class LqrEnv(gym.Env):
def __init__(self, size, init_state, state_bound):
self.init_state = init_state
self.size = size
self.action_space = spaces.Box(low=-state_bound, high=state_bound, shape=(size,))
self.observation_space = spaces.Box(low=-state_bound, high=state_bound, shape=(size,))
self._seed()
def _seed(self, seed=None):
self.np_random, seed = seeding.np_random(seed)
return [seed]
def _step(self,u):
costs = np.sum(u**2) + np.sum(self.state**2)
self.state = np.clip(self.state + u, self.observation_space.low, self.observation_space.high)
return self._get_obs(), -costs, False, {}
def _reset(self):
high = self.init_state*np.ones((self.size,))
self.state = self.np_random.uniform(low=-high, high=high)
self.last_u = None
return self._get_obs()
def _get_obs(self):
return self.state
Add from gym.envs.classic_control.lqr_env import LqrEnv to __init__.py (also in classic_control).
In your script, when you create the environment, do
gym.envs.register(
id='Lqr-v0',
entry_point='gym.envs.classic_control:LqrEnv',
max_episode_steps=150,
kwargs={'size' : 1, 'init_state' : 10., 'state_bound' : np.inf},
)
env = gym.make('Lqr-v0')
Environment registration process can be found here.
Please go through this example custom environment if you have any more issues.
Refer to this stackoverflow issue for further information.
That problem is related to versions of gym try upgrading your gym environment.
There is no detalied explanation of what exactly es6 import and export do under the hood. Someone describe import as an read only view. Check the code below:
// lib/counter.js
export let counter = 1;
export function increment() {
counter++;
}
export function decrement() {
counter--;
}
// src/main.js
import * as counter from '../../counter';
console.log(counter.counter); // 1
counter.increment();
console..log(counter.counter); // 2
My question is if two modules import the same counter module and the first module increment the counter, will the second module also see the the counter as incremented? What under hood do the "import" and "export" do? Under what context is the increment function executing on? What is variable object of the increment function?
// lib/counter.js
export let counter = 1;
export function increment() {
counter++;
}
export function decrement() {
counter--;
}
// src/main1.js
import * as counter from '../../counter';
console.log(counter.counter); // 1
counter.increment();
console..log(counter.counter); // 2
// src/main2.js
import * as counter from '../../counter';
console.log(counter.counter); // what is the result of this, 1 or 2?
It seems to me that the "export" is creating a global object that can be accessed by different modules and it is setting the context of the exported function to that object. If this is the case, the design is wired for me, because modules is not aware of what other modules do. If two modules are importing the same module(counter), one module calls the increment function(example above) which cause the value(counter) changed, the other module does not know that.
See section 16.3.5 here
As mentioned:
The imports of an ES6 module are read-only views on the exported entities. That means that the connections to variables declared inside module bodies remain live, as demonstrated in the following code.
//------ lib.js ------
export let counter = 3;
export function incCounter() {
counter++;
}
//------ main.js ------
import { counter, incCounter } from './lib';
// The imported value `counter` is live
console.log(counter); // 3
incCounter();
console.log(counter); // 4
How that works under the hood is explained in a later section.
Imports as views have the following advantages:
They enable cyclic dependencies, even for unqualified imports.
Qualified and unqualified imports work the same way (they are both
indirections).
You can split code into multiple modules and it will
continue to work (as long as you don’t try to change the values of
imports).
The answer depends on what is your entry module. For example, if you define an entry module as:
// index.js
import "./main1";
import "./main2";
Then the output is:
1 // from main1
2 // from main1
2 // from main2
ES6 modules are allowed hold state, but are not allowed to manipulate others modules state directly. The module itself can expose a modifier function (like your increment method).
If you want to experiment a bit, rollupjs has a nice online demo that shows how the standard imports and exports should work.
What I want to know is, how can I create GUI elements using swing inside a Jython class so that they can be referenced from outside the class, and I can use statements like button.setText("Hello") on an object that was created inside another class. For example:
foo.py:
from javax.swing import *
class Test():
def __init__(self):
frame = JFrame("TEST")
button = JButton("Hey")
frame.add(button)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
frame.setSize(300,200)
frame.show()
and then I have another file called somethingelse.py:
from foo import *
run = Test()
If I were to want to change the button text by using run.button.setText("Message"), how could I organise the Test() class such that I could change the text from the second file, somethingelse.py.
Your code is throwing away the references it has to the controls, so you can't access them from anywhere - frame and button are local variables, and disappear once __init__ returns.
You should (minimally) make them object members:
class Test():
def __init__(self):
self.frame = JFrame("TEST")
self.button = JButton("Hey")
self.frame.add(button)
# ...
You can then say:
from foo import *
run = Test()
run.button.setText("Message")