I just started on Python, and still trying to learn it. I recently started learning Sikulix and its applications. Would highly appreciate if you could share your ideas...
Problem is that I have 3 py files. Say:
main.py
checkInventory.py
startMining.py
I only defined 1 function on checkInventory.py, startMining.py each, functions are also named after the file names (checkInventory(), startMining() respectively)
When I run the main.py it is calling checkInventory() using:
beginning of main.py...
from checkInventoryStatus import *
No problem on this. I can call checkInventoryStatus() function with no problem on main.py.
However, checkInventory() also runs startMining() at some point and it keeps giving this error:
NameError ( global name 'startMining' is not defined )
I am also importing all the content of startMining.py to checkInventory.py using:
beginning of checkInventory.py...
from startMining import *
I tried to import all elements of startMining.py to checkInventory.py but it is failing to call the function startMining() from checkInventory.py.
Main
from startMining import *
from watchMining import *
from checkInventoryStatus import *
def startApp():
KO = switchApp("KL")
checkInventoryStatus()
with open("C:\Users\PC\Desktop\skx\logs.txt", "w") as f:
f.write("App started!\n")
startApp()
checkInventoryStatus
from sikuli import *
from startMining import *
from watchMining import *
def checkInventoryStatus():
if(exists("1673723539914.png")):
if(exists(Pattern("1673723411692.png").exact())):
startMining()
startMining.py
from sikuli import *
from watchMining import *
from checkInventoryStatus import *
def startMining():
wait(0.6)
type(Key.ENTER + "/town" + Key.ENTER)
arrived = False
wait(0.3)
try:
click(Pattern("1673722724479.png").similar(0.58))
wait(1.5)
while(True):
if(exists(Pattern("1673729480660.png").exact())):
click(Pattern("1673729480660.png").exact())
mouseMove((Location(700, 500)))
X_Coordinate_Region = Region(105,75,30,14)
Y_Coordinate_Region = Region(139,77,25,11)
X_Coordinate = X_Coordinate_Region.text()
Y_Coordinate = Y_Coordinate_Region.text()
X_temp = X_Coordinate_Region.text()
Y_temp = Y_Coordinate_Region.text()
wait(0.45)
X_Coordinate_Region = Region(105,75,30,14)
Y_Coordinate_Region = Region(139,77,25,11)
X_Coordinate = X_Coordinate_Region.text()
Y_Coordinate = Y_Coordinate_Region.text()
if X_temp==X_Coordinate_Region.text() and Y_temp==Y_Coordinate_Region.text() and arrived==False:
startMining()
try:
if abs(int(X_Coordinate_Region.text())-1490)<30 and abs(int(Y_Coordinate_Region.text())-540)<30:
arrrived=True
type("s")
mouseMove(mouseMove(Location(0, 500)))
wait(0.95)
mouseMove((Location(700, 500)))
click(Pattern("1673398228807.png").similar(0.50))
while(True):
if(exists(Pattern("1673729480660.png").exact())):
click(Pattern("1673729480660.png").exact())
mouseMove((Location(700, 500)))
arrived=False
try:
if abs(int(X_Coordinate_Region.text())-1453)<30 and abs(int(Y_Coordinate_Region.text())-380)<30:
arrrived=True
type("s")
type(" ")
break
except:
continue
except:
continue
#f.write("\nX:" +X_Coordinate+" Y: "+Y_Coordinate+"\n")
with open("C:\Users\PC\Desktop\skx\logs.txt", "a") as f:
f.write("\nX:" +X_Coordinate+" Y: "+Y_Coordinate+"\n")
wait(0.5)
except:
mouseMove(mouseMove(Location(0, 500)))
wait(0.4)
mouseMove((Location(700, 500)))
startMining()
Here is the error message:
[error] script [ main ] stopped with error in line 13
[error] NameError ( global name 'startMining' is not defined )
[error] --- Traceback --- error source first
line: module ( function ) statement
9: checkInventoryStatus ( checkInventoryStatus ) startMining()
8: main ( startApp ) checkInventoryStatus()
13: main ( <module> ) startApp()
[error] --- Traceback --- end --------------
I believe it is due to "circular import" behavior between checkInventoryStatus.py and startMining.py.
You can structure your code in a way that eliminates calling modules in a circular motion. For example, you can move checkInventoryStatus() into startMining.py which will kill the dependency to checkInventoryStatus.py (assuming that all you code consists of only these three scripts.)
Related
I am trying to follow a ROS2 testing tutorial which tests a topic listener to understand how ROS2 testing works. Here is a screenshot of the related code at 21:15
I have a node target_control_node which subscribes the topic turtle1/pose and then move the turtle to a new random pose.
import math
import random
import rclpy
from geometry_msgs.msg import Twist
from rclpy.node import Node
from turtlesim.msg import Pose
class TargetControlNode(Node):
def __init__(self):
super().__init__("target_control_node")
self.get_logger().info("target_control_node")
self._target_pose = None
self._cmd_vel_publisher = self.create_publisher(Twist, "turtle1/cmd_vel", 10)
self.create_subscription(Pose, "turtle1/pose", self.subscribe_target_pose, 10)
self.create_timer(1.0, self.control_loop)
def subscribe_target_pose(self, msg):
self._target_pose = msg
def control_loop(self):
if self._target_pose is None:
return
target_x = random.uniform(0.0, 10.0)
target_y = random.uniform(0.0, 10.0)
dist_x = target_x - self._target_pose.x
dist_y = target_y - self._target_pose.y
distance = math.sqrt(dist_x**2 + dist_y**2)
msg = Twist()
# position
msg.linear.x = 1.0 * distance
# orientation
goal_theta = math.atan2(dist_y, dist_x)
diff = goal_theta - self._target_pose.theta
if diff > math.pi:
diff -= 2 * math.pi
elif diff < -math.pi:
diff += 2 * math.pi
msg.angular.z = 2 * diff
self._cmd_vel_publisher.publish(msg)
def main(args=None):
rclpy.init(args=args)
node = TargetControlNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == "__main__":
main()
I am trying to write a simple test for the subscription part based on the tutorial above to understand how it works.
Here is my initial test code. Note inside I am using expected_output=str(msg), however, it is wrong, and I am not sure what to put there.
import pathlib
import random
import sys
import time
import unittest
import uuid
import launch
import launch_ros
import launch_testing
import pytest
import rclpy
import std_msgs.msg
from geometry_msgs.msg import Twist
from turtlesim.msg import Pose
#pytest.mark.rostest
def generate_test_description():
src_path = pathlib.Path(__file__).parent.parent
target_control_node = launch_ros.actions.Node(
executable=sys.executable,
arguments=[src_path.joinpath("turtle_robot/target_control_node.py").as_posix()],
additional_env={"PYTHONUNBUFFERED": "1"},
)
return (
launch.LaunchDescription(
[
target_control_node,
launch_testing.actions.ReadyToTest(),
]
),
{
"target_control_node": target_control_node,
},
)
class TestTargetControlNodeLink(unittest.TestCase):
#classmethod
def setUpClass(cls):
rclpy.init()
#classmethod
def tearDownClass(cls):
rclpy.shutdown()
def setUp(self):
self.node = rclpy.create_node("target_control_test_node")
def tearDown(self):
self.node.destroy_node()
def test_target_control_node(self, target_control_node, proc_output):
pose_pub = self.node.create_publisher(Pose, "turtle1/pose", 10)
try:
msg = Pose()
msg.x = random.uniform(0.0, 10.0)
msg.y = random.uniform(0.0, 10.0)
msg.theta = 0.0
msg.linear_velocity = 0.0
msg.angular_velocity = 0.0
pose_pub.publish(msg)
success = proc_output.waitFor(
# `str(msg)` is wrong, however, I am not sure what to put here.
expected_output=str(msg), process=target_control_node, timeout=1.0
)
assert success
finally:
self.node.destroy_publisher(pose_pub)
When I run launch_test src/turtle_robot/test/test_target_control_node.py, it only prints this without telling me what is actual output:
[INFO] [launch]: All log files can be found below /home/parallels/.ros/log/2023-01-02-16-37-27-631032-ubuntu-linux-22-04-desktop-1439830
[INFO] [launch]: Default logging verbosity is set to INFO
test_target_control_node (test_target_control_node.TestTargetControlNodeLink) ... [INFO] [python3-1]: process started with pid [1439833]
[python3-1] [INFO] [1672706247.877402445] [target_control_node]: target_control_node
FAIL
======================================================================
FAIL: test_target_control_node (test_target_control_node.TestTargetControlNodeLink)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/my-ros/src/turtle_robot/test/test_target_control_node.py", line 91, in test_target_control_node
assert success
AssertionError
----------------------------------------------------------------------
Ran 1 test in 1.061s
FAILED (failures=1)
[INFO] [python3-1]: sending signal 'SIGINT' to process[python3-1]
[python3-1] Traceback (most recent call last):
[python3-1] File "/my-ros/src/turtle_robot/turtle_robot/target_control_node.py", line 59, in <module>
[python3-1] main()
[python3-1] File "/my-ros/src/turtle_robot/turtle_robot/target_control_node.py", line 53, in main
[python3-1] rclpy.spin(node)
[python3-1] File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/__init__.py", line 222, in spin
[python3-1] executor.spin_once()
[python3-1] File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 705, in spin_once
[python3-1] handler, entity, node = self.wait_for_ready_callbacks(timeout_sec=timeout_sec)
[python3-1] File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 691, in wait_for_ready_callbacks
[python3-1] return next(self._cb_iter)
[python3-1] File "/opt/ros/humble/local/lib/python3.10/dist-packages/rclpy/executors.py", line 588, in _wait_for_ready_callbacks
[python3-1] wait_set.wait(timeout_nsec)
[python3-1] KeyboardInterrupt
[ERROR] [python3-1]: process has died [pid 1439833, exit code -2, cmd '/usr/bin/python3 /my-ros/src/turtle_robot/turtle_robot/target_control_node.py --ros-args'].
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
I checked the source code of waitFor, but still no clue.
Is there a way to print the actual output so that I can give correct expected_output? Thanks!
To answer your question(and give some more general tips): You can always print out the msg inside the node. That said, the reason you're getting an error is because msg is a ros message type, meaning it's an object. So by doing str(msg) your expected output will be something like <object of type Pose at (some_address)>; and not the actual message values. Also since it appears you're just testing a subscriber, it doesn't usually make sense to have a unit test that's expecting stdout. I would also note that you're publishing a message before actually waiting for the result, this should always fail. The reason is because by the time your subscriber is started, the message has already been published and is gone.
Finally, you shouldn't have a publisher included in any unit tests. It adds an extra dependency and since it's a prepackaged transport layer testing if it works is irrelevant. Instead to fix your problem you should simply be calling the individual methods of your node directly. Basically import the script, instantiate the object, and don't try to deal with the whole node lifecycle.
Edit based on comments
Looking at your subscriber code, you'll need to actually print something out. Unfortunately because it's not a std_msg(i.e. it has more fields than just .data) you'll need to decide how you want to go about confirming the data is right. You could simply look at one field or all of them in order. For example you might have in your test:
success = proc_output.waitFor(
expected_output=str(msg.x),
process=target_control_node, timeout=1.0)
And in your control node:
def subscribe_target_pose(self, msg):
self._target_pose = msg
print(msg.x)
That said, this IO handling method doesn't seem like the best to me. Mainly because it relies on stdout which isn't something you always want.
I'm calling a python code from a java code using Jython by PythonInterpreter. The python code is this:
from pdfrw import PdfReader, PdfWriter, PageMerge
import sys
def resize(thread_name):
pages = PdfReader('C:/MY/PATH/download.pdf').pages
output = PdfWriter()
rects = [[float(num) for num in page.MediaBox] for page in pages]
height = max(x[3] - x[1] for x in rects)
width = max(x[2] - x[0] for x in rects)
mbox = [0, 0, width, height]
for page in pages:
newpage = PageMerge()
newpage.mbox = mbox # Set boundaries of output page
newpage.add(page) # Add one old page to new page
image = newpage[0] # Get image of old page (first item)
image.x = (width - image.w) / 2 # Center old page left/right
image.y = (height - image.h) # Move old page to top of output page
output.addpage(newpage.render())
output.write('C:/MY/PATH/' + thread_name + 'tmp_processed.pdf')
return "finished"
arg1 = sys.argv[1]
resize(arg1)
and this is the Java code:
String pathPython = PATH.concat("pdf.py");
String threadName = Thread.currentThread().getName();
PythonInterpreter interpreter = new PythonInterpreter();
interpreter.execfile(pathPython);
interpreter.set("thread_name", threadName);
PyObject str = interpreter.eval(String.format("repr(resize(%s))", threadName));
System.out.println(str.toString());
When I run the Java code I'm getting this error:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is Traceback (most recent call last):
File "C:/MY/PATH/pdf.py", line 1, in <module>
from pdfrw import PdfReader, PdfWriter, PageMerge
**ImportError: No module named pdfrw**
] with root cause
org.python.core.PyException: null
How can I solve it?
Thanks in advance
I downloaded the code from here https://github.com/SpaceNetChallenge/SpaceNet_SAR_Buildings_Solutions, specifically using model 1. I downloaded the weights corresponding and created the following file to load the model and test. First, I copy the Unet part in main.py into a separate file umodel.py and the test file as follows
import torch
exec(open("./umodel.py").read())
network_data = torch.load('snapshot_fold_8_best')
print(network_data.keys())
import sys
sys.path.append("geffnet")
class Namespace:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
args = Namespace(extra_num = 1,
dec_ch = [32, 64, 128, 256, 1024],
stride=32,
net='b5',
bot1x1=True,
glob=True,
bn=True,
aspp=True,
ocr=True,
aux_scale=True)
def load_state_dict(model, state_dict):
missing_keys = []
# from UnetOS.umodel import Unet
exec(open("./umodel.py").read())
try:
from torch.hub import load_state_dict_from_url
except ImportError:
from torch.utils.model_zoo import load_url as load_state_dict_from_url
# from UnetOS.umodel import *
model = Unet(extra_num = args.extra_num, dec_ch = args.dec_ch, stride=args.stride, net=args.net, bot1x1 = args.bot1x1, glob=args.glob, bn=args.bn, aspp=args.aspp,
ocr=args.ocr, aux = args.aux_scale > 0).cuda()
load_state_dict(model, network_data)
My question is, why exec(open("./umodel.py").read()) works nicely but whenever I tried to import from umodel import Unet it has errors
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_10492/1282530406.py in <module>
9 # ah
10 model = Unet(extra_num = args.extra_num, dec_ch = args.dec_ch, stride=args.stride, net=args.net, bot1x1 = args.bot1x1, glob=args.glob, bn=args.bn, aspp=args.aspp,
---> 11 ocr=args.ocr, aux = args.aux_scale > 0).cuda()
12 #model = Unet()
13 #print(network_data.key())
D:\hines\Pretrained\1-zbigniewwojna\UnetOS\umodel.py in __init__(self, extra_num, dec_ch, stride, net, bot1x1, glob, bn, aspp, ocr, aux)
238 ['ir_r4_k5_s2_e6_c192_se0.25'],
239 ['ir_r1_k3_s1_e6_c320_se0.25']]
--> 240 enc = GenEfficientNet(in_chans=3, block_args=decode_arch_def(arch_def, depth_multiplier),
241 num_features=round_channels(1280, channel_multiplier, 8, None), stem_size=32,
242 channel_multiplier=channel_multiplier, act_layer=resolve_act_layer({}, 'swish'),
NameError: name 'decode_arch_def' is not defined
The main file is as follow https://github.com/SpaceNetChallenge/SpaceNet_SAR_Buildings_Solutions/blob/master/1-zbigniewwojna/main.py
From the error message, it appears that decode_arch_def is not available and looking at your imports, that has to come from from geffnet.efficientnet_builder import * (it does https://github.com/rwightman/gen-efficientnet-pytorch/blob/master/geffnet/efficientnet_builder.py)
Your exec must have worked because it followed a similar import, that brought decode_arch_def in scope - exec() executes code in the current scope, so it will work because in that scope decode_arch_def is already defined.
However, when you import, the imported module itself doesn't have the function you need in scope. You should add the required import statements to the file you're importing to bring them into scope and it should work.
For example, with a mod.py containing this:
def my_func():
print(datetime.now())
This works:
from datetime import datetime
exec(open("./mod.py").read())
my_func()
But this does not:
from datetime import datetime
import mod
mod.my_func()
To make that work, mod.py would have to be:
from datetime import datetime
def my_func():
print(datetime.now())
And the import of datetime wouldn't be needed in the main program, since it's not referenced there. Your code has a similar issue - you need to determine all the dependencies of your Unet class and import them.
the line : with open('new%s.txt' % intg ,'a') as g : is giving error in below code.
Every time I call the function "Repeat", it should create file with name new1.txt, new2.txt and so on.
But it is giving error : "name 'intg' is not defined"
I want dynamic name for screenshot file and txt file, to prevent overwriting of file.
The code is for selecting data from a software, copying it, and pasting it in new file each time.
Please help:
import win32api
import win32com.client
import pyautogui
import pyperclip
shell = win32com.client.Dispatch("WScript.Shell")
win32api.Sleep(5000)
def repeat( intg ):
import pyautogui
pyautogui.moveTo(17, 213)
win32api.Sleep(2000)
pyautogui.screenshot('%s.png' % intg)
pyautogui.click()
win32api.Sleep(2000)
pyautogui.hotkey('ctrl', 'c')
s = pyperclip.paste()
win32api.Sleep(2000)
with open('new%s.txt' % intg ,'a') as g:
g.write(s)
print("done")
repeat( intg = 1 )
repeat( intg = 2 )
win32api.Sleep(5000)
print ("done")
you can concatenate integer and strings doing so:
with open('new' + str(intg) + '.txt','a') as g:
or doing so:
with open('new{0}.txt'.format(intg),'a') as g:
I am trying to grab an input from my main.py file using tkinter and then use that input in runAnalytics.py
main.py
import runAnalytics
import tkinter
import os
import centerWindow
loadApplication = tkinter.Tk()
loadApplication.title("Stock Analytics")
loadApplication.geometry("1080x720")
label1 = tkinter.Label(loadApplication, text = "Ticker")
input1 = tkinter.Entry(loadApplication)
loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = runAnalytics.run)
centerWindow.center(loadApplication)
loadAnalytics.pack()
label1.pack()
input1.pack()
loadApplication.mainloop()
runAnalytics.py
from yahoo_finance import Share
from main import input1
import tkinter
import os
import centerWindow
def run():
ticker = input1
loadAnalytics = tkinter.Tk()
loadAnalytics.title("$" + ticker + " Data")
loadAnalytics.geometry("1080x720")
print ("Price per share: " + ticker.get_price())
ticker.refresh()
print ("Price per share: " + ticker.get_price())
print("The dividend yield is: " + ticker.get_dividend_yield())
print("The 52 week low is: " + ticker.get_year_low())
print("The 52 week high is: " + ticker.get_year_high())
print("The volume is: " + ticker.get_volume())
print("The previous close was: " + ticker.get_prev_close())
print("The previous open was: " + ticker.get_open())
loadAnalytics.mainloop()
My error message reads as follows;
Traceback (most recent call last):
File "C:\Users\MyName\Documents\Python Projects\MarketData\main.py", line 1, in <module>
import runAnalytics
File "C:\Users\MyName\Documents\Python Projects\MarketData\runAnalytics.py", line 2, in <module>
from main import input1
File "C:\Users\MyName\Documents\Python Projects\MarketData\main.py", line 13, in <module>
loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = runAnalytics.run)
AttributeError: module 'runAnalytics' has no attribute 'run'
You have a circular import:
import runAnalytics
# ..
from main import input1
By the time main is being imported again, runAnalytics has not yet had a chance to execute the def run():.. section.
Resolve this by removing the from main import input1 line, and pass that object in as an argument instead:
def run(input1):
passing this in from the main.py module when you call the function:
loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = lambda: runAnalytics.run(input1))
Apart from the circular import, there is also the issue that whatever file you run as the main script in Python will be stored as the __main__ module. Importing that same script again will lead to a second module being created, now under the name main, and any objects created in that module are distinct from those in __main__.
Next, you'll want to remove the loadAnalytics.mainloop() call from run as you should not start a new mainloop from an already running loop. You probably also want to create a new TopLevel window instead of creating another Tk() root. You'd have to pass in loadApplication to run too if you go this way.
from runAnalytics import run
loadAnalytics = tkinter.Button(loadApplication, text="Load Analytics", command=run)
You don't want to start another mainloop of tk. Instead you should pass the root and create a toplevel window.
def run(root):
ticker = input1
parent = Toplevel(root)
parent.title("$" + ticker + " Data")
# the rest of your code
Try adding () to the end of runAnalytics.run. You are currently telling it to look for a run attribute which it doesn't have instead of a function
loadAnalytics = tkinter.Button(loadApplication, text = "Load Analytics", command = runAnalytics.run())