I'm unsure again with something what I'm sure is going to be very simple...
Basically, I'm trying to make my first script call/execute a bunch of other scripts but the problem is I want each individual script to contain its own functions not be called from the first secript...
First script/main script:
from datetime import date, timedelta
from sched import scheduler
from time import time, sleep, strftime
import random
s = scheduler(time, sleep)
random.seed()
def periodically(runtime, intsmall, intlarge, function):
## Get current time
currenttime = strftime('%H:%M:%S')
## If currenttime is anywhere between 23:40 and 23:50 then...
if currenttime > '23:40:00' and currenttime < '23:50:00':
## Call clear
clear()
## Update time
currenttime = strftime('%H:%M:%S')
## Idle time
while currenttime > '23:40:00' and currenttime < '23:59:59' or currenttime >= '00:00:00' and currenttime < '01:30:00':
## Update time
currenttime = strftime('%H:%M:%S')
runtime += random.randrange(intsmall, intlarge)
s.enter(runtime, 1, function, ())
s.run()
def callscripts():
print "Calling Functions"
errors = open('ERROR(S).txt', 'a')
try:
execfile("data/secondary.py")
except Exception as e:
errors.write(str(e))
errors.write("""
""")
errors.close()
while True:
periodically(2, -1, +1, callscripts)
Below is secondary.py
import win32con
from win32api import *
from win32gui import *
class WindowsBalloonTip:
def __init__(self, title, msg):
message_map = { win32con.WM_DESTROY: self.OnDestroy,}
# Register the window class.
wc = WNDCLASS()
hinst = wc.hInstance = GetModuleHandle(None)
wc.lpszClassName = 'PythonTaskbar'
wc.lpfnWndProc = message_map # could also specify a wndproc.
classAtom = RegisterClass(wc)
# Create the window.
style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU
self.hwnd = CreateWindow(classAtom, "Taskbar", style, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, hinst, None)
UpdateWindow(self.hwnd)
# Icons managment
iconPathName = "icon1.ico" ## LOCATION TO THE ICON FILE
icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
try:
hicon = LoadImage(hinst, iconPathName, win32con.IMAGE_ICON, 0, 0, icon_flags)
except:
hicon = LoadIcon(0, win32con.IDI_APPLICATION)
flags = NIF_ICON | NIF_MESSAGE | NIF_TIP
nid = (self.hwnd, 0, flags, win32con.WM_USER+20, hicon, 'Tooltip')
# Notify
Shell_NotifyIcon(NIM_ADD, nid)
Shell_NotifyIcon(NIM_MODIFY, (self.hwnd, 0, NIF_INFO, win32con.WM_USER+20, hicon, 'Balloon Tooltip', msg, 200, title))
# self.show_balloon(title, msg)
sleep(5)
# Destroy
DestroyWindow(self.hwnd)
classAtom = UnregisterClass(classAtom, hinst)
def OnDestroy(self, hwnd, msg, wparam, lparam):
nid = (self.hwnd, 0)
Shell_NotifyIcon(NIM_DELETE, nid)
PostQuitMessage(0) # Terminate the app.
# Function
def balloon_tip(title, msg):
w=WindowsBalloonTip(title, msg)
balloon_tip("test test", "Running")
def hi():
print "hi"
hi()
Error:
global name 'WindowsBalloonTip' is not defined
Full Error:
Traceback (most recent call last):
File "C:\Main.py", line 48, in <module>
periodically(2, -1, +1, callscripts)
File "C:\Main.py", line 27, in periodically
s.run()
File "C:\Python27\lib\sched.py", line 117, in run
action(*argument)
File "Main.py", line 34, in callscripts
execfile("data/secondary.py")
File "data/secondary.py", line 93, in <module>
balloon_tip("test test", "Running")
File "data/secondary.py", line 78, in balloon_tip
w=WindowsBalloonTip(title, msg)
NameError: global name 'WindowsBalloonTip' is not defined
How would I go about fixing this?
Thanks in advance
Hyflex
First of all,
class WindowsBalloonTip:
should be
class WindowsBalloonTip(object):
because the former is an old style class, which has disappeared in Python 3 and is in recent versions of Python 2.x only for backwards compatibility.
Ethan's answer is correct, but probably unclear to you if you're asking this question. A full explanation is here.
When ballon_tip() is run, it first searches the local namespace -- balloon_tip()'s namespace -- for something called WindowsBalloonTip. When it can't find it, it searches the global namespace. Since you didn't provide anything to the globals parameter to execfile(), it defaults to the namespace of callscripts(), which doesn't have anything named WindowsBaloonTip inside of it, and errors.
To fix this, you can pass globals() as an argument to execfile, but this will pollute the global namespace of your main script, which you probably don't want. You can also declare everything inside of secondary.py to be global, but you probably don't want to do that since the whole point is to test secondary.py.
The issue is execfile. execfile is an ugly, hack-y way to do things. import is better. One solution would be to write something like this inside secondary.py:
def test_harness():
balloon_tip("test test", "Running")
hi()
then, import secondary, traceback inside your main script, and change callscripts() like this:
def callscripts():
print "Calling Functions"
errors = open("ERRORS(S).txt", "a")
try:
secondary.test_harness()
except:
errors.write(traceback.format_exc() + '\n')
EDIT in response to comment:
At the top of your script, import traceback, then:
def callscripts():
print "Calling Functions"
errors = open("ERRORS(S).txt", "a")
try:
execfile("data/secondary.py", {})
except:
errors.write(traceback.format_exc() + '\n')
The problem is execfile.
Basically, execfile is a fancy exec with a file. So when you call execfile 'secondary.py' Python executes all the lines of secondary.py in the context of where execfile was called. Which, in this case, is inside the callscripts function.
What you probably want is subprocess.
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 would like to be able to start a testmodule that is in my CANoe script; it works fine if I start everything without Python.
Now, my Python code can load CANoe, open the desired cfg, and start the simulation.
I tried some code from examples in the documentation and here, but it doesnt work...
# --------------------------------------------------------------------------
# Standard library imports
import os
import sys
import subprocess
# import win32com.client
import time
import threading
from win32com.client import *
from win32com.client.connect import *
my_xml_ts = r"C:\_my_path\boaz_test2.xml"
# Vector Canoe Class
class CANoe:
def __init__(self):
self.application = None
# check if there is any instance of CANoe process
# output = subprocess.check_output('tasklist', shell=True)
# if CANoe process is still available, kill the process
# if "CANoe32.exe" in str(output):
# os.system("taskkill /im CANoe32.exe /f 2>nul >nul")
# re-dispatch object for CANoe Application
self.application = win32com.client.DispatchEx("CANoe.Application")
self.ver = self.application.Version
print('Loaded CANoe version ',
self.ver.major, '.',
self.ver.minor, '.',
self.ver.Build, '...')#, sep,''
self.Measurement = self.application.Measurement.Running
print(self.Measurement)
def open_simulation(self, cfgname):
# open CANoe simulation
if (self.application != None):
# check for valid file and it is *.cfg file
if os.path.isfile(cfgname) and (os.path.splitext(cfgname)[1] == ".cfg"):
self.application.Open(cfgname)
else:
raise RuntimeError("Can't find CANoe cfg file")
else:
raise RuntimeError("CANoe Application is missing,unable to open simulation")
def set_testmodule(self):
print("set_testmodule start")
test_env = self.application.Configuration.TestSetup.TestEnvironments.Item("Test Environment")
print("set_testmodule 1")
test_env = win32com.client.CastTo(test_env, "ITestEnvironment2")
print("set_testmodule 2")
self.test_module = test_env.TestModules.Item("XML_Boaz_2")
print("set_testmodule end", self.test_module)
def test_module_run(self):
print("test_module_run start")
self.test_module.Start()
print("test_module_run end")
# {.Sequence} property returns a collection of <TestCases> or <TestGroup>
# or <TestSequenceItem> which is more generic
seq = self.test_module.Sequence
for i in range(1, seq.Count + 1):
# Cast from <ITestSequenceItem> to <ITestCase> to access {.Verdict}
# and the {.Enabled} property
tc = win32com.client.CastTo(seq.Item(i), "ITestCase")
if tc.Verdict != 1: # Verdict 1 is pass
tc.Enabled = True
print(f"Enabling Test Case {tc.Ident} with verdict {tc.Verdict}")
else:
tc.Enabled = False
print(f"Disabling Test Case {tc.Ident} since it has already passed")
def close_simulation(self):
# close CANoe simulation
if (self.application != None):
self.stop_Measurement()
self.application.Quit()
# make sure the CANoe is close properly, otherwise enforce taskkill
output = subprocess.check_output('tasklist', shell=True)
if "CANoe32.exe" in str(output):
os.system("taskkill /im CANoe32.exe /f 2>nul >nul")
self.application = None
def start_Measurement(self):
retry = 0
retry_counter = 5
# try to establish measurement within 20s timeout
while not self.application.Measurement.Running and (retry < retry_counter):
self.application.Measurement.Start()
time.sleep(1)
retry += 1
if (retry == retry_counter):
raise RuntimeWarning("CANoe start measuremet failed, Please Check Connection!")
and running that:
import Python_CANoe
import time
import random
def try2():
X = random.randrange(50)
Y = random.randrange(100)
print("start")
CANoe = Python_CANoe.CANoe()
CANoe.open_simulation(canoe_config_file)
CANoe.set_testmodule() # Doesn't work
print("CANoe script already Open")
CANoe.start_Measurement()
time.sleep(5)
CANoe.test_module_run() # Doesn't work
if __name__ == "__main__":
try2()
and this is the error code I am getting:
set_testmodule start
Traceback (most recent call last):
File "C:/Users/m.m/Documents/Python/CANoe_Python_Script/7_5_2021_3_for_stackoverflow/CANoe_Boaz_Test.py", line 133, in <module>
try2()
File "C:/Users/m.m/Documents/Python/CANoe_Python_Script/7_5_2021_3_for_stackoverflow/CANoe_Boaz_Test.py", line 77, in try2
CANoe.set_testmodule() # Doesn't work
File "C:\Users\m.m\Documents\Python\CANoe_Python_Script\7_5_2021_3_for_stackoverflow\Python_CANoe.py", line 52, in set_testmodule
test_env = self.application.Configuration.TestSetup.TestEnvironments.Item("Test Environment")
File "C:\Users\BOAZ~1.BIL\LOCALS~1\Temp\gen_py\3.7\7F31DEB0-5BCC-11D3-8562-00105A3E017Bx0x1x58.py", line 15873, in Item
ret = self._oleobj_.InvokeTypes(0, LCID, 2, (9, 0), ((12, 1),),index
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'TestEnvironments::Item', 'Invalid index: Item not found!', 'C:\\Program Files\\Vector CANoe 11.0\\Help01\\CANoeCANalyzer.chm', 4281, -2147467259), None)
I am very new in python cffi. I have to access my temprature module by using its Index or with its channel name. I am trying with both as you can see in my QmixTC class. I am getting attribute error. In other class, there is no errors. Can someone help me understand where is the problem. I am putting my code as well as error trace. Thanks.
main code with name qmix.py (importing it in to sample code):
class QmixTC (object):
"""
"""
def __init__(self, index=0, handle=None,name=''):
self.dll_dir = DLL_DIR
self.dll_file = os.path.join(self.dll_dir,
'labbCAN_Controller_API.dll')
self._ffi = FFI()
self._ffi.cdef(CONTROLLER_HEADER)
self._dll = self._ffi.dlopen(self.dll_file)
self._handle = self._ffi.new('dev_hdl *', 0)
if handle is None:
self.index = index
self._handle = self._ffi.new('dev_hdl *', 0)
self._call('LCC_GetChannelHandle', self.index, self._handle)
else:
self.index = None
self._handle = handle
self._ch_name="QmixTC_1_DO0_INA"
self._channel = self._ch_name + str(index)
self._call('LCC_LookupChanByName',
bytes(self._channel,'utf8'),
self._handle)
self.name = name
def _call(self, func_name, *args):
func = getattr(self._dll, func_name)
r = func(*args)
r = CHK(r, func_name, *args)
return r
def Setpoint_write (self, setpoint):
"""
Write setpoint value to controller device.
Parameters
[in] ChanHdl Valid handle of open controller channel
[in] fSetPointValue The setpoint value to write
Returns
Error code - ERR_NOERR indicates success
"""
self._call('LCC_WriteSetPoint', self._handle[0], setpoint)
def enable_controllLoop (self, enable):
"""
Enables / disables a control loop.
If the control loop is enabled, then the output value is calculated periodically.
Parameters
ChanHdl Valid handle of a controller channel
Enable 1 = enable, 0 = disable
Returns
Error code - ERR_NOERR indicates success
"""
self._call('LCC_EnableControlLoop', self._handle[0], enable)
def read_temp_value (self, actualvalue):
"""
Read actual value from device.
Parameters
[in] ChanHdl Valid handle of open controller channel
[out] pfActualValue Returns the actual controller value
Returns
Error code - ERR_NOERR indicates success
"""
self._call('LCC_ReadActualValue', self._handle[0], actualvalue)
if __name__ == '__main__':
import os.path as op
dll_dir = op.normpath('C:\\Users\\Ravikumar\\AppData\\Local\\QmixSDK')
config_dir = op.normpath('C:\\Users\\Public\\Documents\\QmixElements\\Projects\\QmixTC_Pump\\Configurations\\QmixTC_pump')
bus = QmixBus(config_dir=config_dir)
bus.open()
bus.start()
controller_0 = QmixTC(index=0)
controller_0.enable_controllLoop(1)
sample program:
from __future__ import division, print_function
from win32api import GetSystemMetrics
import numpy as np
import os
import qmix
import pandas as pd
#%% CHANNEL INITIALIZATION
if __name__ == '__main__':
dll_dir = ('C:\\Users\\Ravikumar\\AppData\\Local\\QmixSDK')
config_dir = ('C:\\Users\\Public\\Documents\\QmixElements\\Projects\\QmixTC_test1\\Configurations\\QmixTC_test1')
qmix_bus = qmix.QmixBus(config_dir=config_dir,dll_dir=dll_dir)
qmix_bus.open()
qmix_bus.start()
controller_0 = qmix.QmixTC(index=0)
controller_0.Setpoint_write(50)
error:
Traceback (most recent call last):
File "<ipython-input-5-40d4a3db9493>", line 17, in <module>
controller_0 = qmix.QmixTC(index=0)
File "qmix.py", line 921, in __init__
self._call('LCC_GetChannelHandle', self.index, self._handle)
File "qmix.py", line 937, in _call
func = getattr(self._dll, func_name)
File "C:\Users\Ravikumar\Anaconda2\lib\site-packages\cffi\api.py", line 875, in __getattr__
make_accessor(name)
File "C:\Users\Ravikumar\Anaconda2\lib\site-packages\cffi\api.py", line 870, in make_accessor
raise AttributeError(name)
AttributeError: LCC_GetChannelHandle
I have updated this code with modifications suggested by Reticality. I would like to access the value of hands_count which resides within the array of packets[] and or the array type[] below.
def history2packets(self, history, game_id, cache):
game_index = 0
player_list_index = 7
packets = []
for event in history:
self.event = event
type = event[0]
if type == "game":
(type, level, hand_serial, hands_count, time, variant, betting_structure, player_list, dealer, serial2chips) = event
if len(serial2chips) > 1:
nochips = 0
for (serial, chips) in serial2chips.iteritems():
if serial == 'values':
continue
packets.append(PacketPokerPlayerChips(game_id = game_id,
serial = serial,
bet = nochips,
money = chips))
packets.append(PacketPokerInGame(game_id = game_id,
players = player_list))
if self.previous_dealer == dealer:
previous_dealer = -1
else:
previous_dealer = self.previous_dealer
packets.append(PacketPokerDealer(game_id = game_id,
dealer = dealer,
previous_dealer = previous_dealer))
self.previous_dealer = dealer
packets.append(PacketPokerStart(game_id = game_id,
hand_serial = hand_serial,
hands_count = hands_count,
time = time,
level = level))
and use that value in another function like so:
def autoDeal(self):
self.cancelDealTimeout()
if not self.allReadyToPlay():
for player in self.game.playersAll():
if player.getUserData()['ready'] == False:
for avatar in self.avatar_collection.get(player.serial):
if self.factory.verbose > 1:
self.message("Player %d marked as having a bugous PokerProcessingHand protocol" % player.serial)
avatar.bugous_processing_hand = True
if self.event[2] != 0:
self.beginTurn()
self.update()
else:
reactor.callLater(10, self.beginTurn)
self.update()
I am still getting an error but a different one.
2015-02-19 22:10:11-0500 [-] Unhandled Error
Traceback (most recent call last):
File "/usr/lib/python2.6/dist-packages/twisted/application/app.py", line 445, in startReactor
self.config, oldstdout, oldstderr, self.profiler, reactor)
File "/usr/lib/python2.6/dist-packages/twisted/application/app.py", line 348, in runReactorWithLogging
reactor.run()
File "/usr/lib/python2.6/dist-packages/twisted/internet/base.py", line 1170, in run
self.mainLoop()
File "/usr/lib/python2.6/dist-packages/twisted/internet/base.py", line 1179, in mainLoop
self.runUntilCurrent()
--- <exception caught here> ---
File "/usr/lib/python2.6/dist-packages/twisted/internet/base.py", line 778, in runUntilCurrent
call.func(*call.args, **call.kw)
File "/usr/lib/python2.6/dist-packages/pokernetwork/pokertable.py", line 738, in autoDeal
if self.event[2] != 0:
exceptions.AttributeError: PokerTable instance has no attribute 'event'
Both function are within the same module and class. What else could be wrong?
The variable event is defined within the local scope of the method history2packets. If you refer to it within another scope (e.g. a function or method) it will raise a NameError, as it was not defined in that scope.
A quick way to fix this is putting a line saying global event at the top of both methods, but this is usually frowned upon. Another way is returning event from history2packets and make the parameters of autoDeal autoDeal(self, event). This means you could call:
e = history2packets(...)
# 5 lines later
autodeal(e)
Another way to do this assumes history2packets and autoDeal are 2 methods of the same class. Modify dome code here in history2packets:
packets = []
for event in history:
self.event = event
type = event[0]
And then, make autoDeal
def autoDeal(self):
self.cancelDealTimeout()
if not self.allReadyToPlay():
# Some lines later
if self.event[2] != 0: # This is the changed line
# Same as before
The variable event is defined in history2packets, but it is not global. So when you refer to a variable with this name in a different function, that raises a NameError.
Trying to create a python script to do a periodic check on a service. If it is not running, it will auto-start it. Here is the code:
import win32serviceutil
from sched import scheduler
from time import time, sleep
s = scheduler(time, sleep)
def run_periodically(start, end, interval, func):
event_time = start
while event_time < end:
s.enterabs(event_time, 0, func, ())
event_time += interval
s.run()
if __name__ == '__main__':
machine = 'George'
service = 'Hamachi2Svc'
action = 'start'
def service_info(action, machine, service):
if win32serviceutil.QueryServiceStatus(service, machine)[1] == 4:
print "%s is currently running" % service
else:
print "%s is *not* running" % service
print "%s is starting..." % service
win32serviceutil.StartService(service, machine)
print '%s started successfully' % service
run_periodically(time()+5, time()+10, 1, service_info(action, machine, service))
Here is the error produced:
Traceback (most recent call last):
File "C:\Python27\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 323, in RunScript
debugger.run(codeObject, __main__.__dict__, start_stepping=0)
File "C:\Python27\Lib\site-packages\pythonwin\pywin\debugger\__init__.py", line 60, in run
_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
File "C:\Python27\Lib\site-packages\pythonwin\pywin\debugger\debugger.py", line 655, in run
exec cmd in globals, locals
File "C:\Users\Administrator\Desktop\HamachiDestroyerV.01.py", line 1, in <module>
import win32serviceutil
File "C:\Users\Administrator\Desktop\HamachiDestroyerV.01.py", line 13, in run_periodically
s.run()
File "C:\Python27\lib\sched.py", line 117, in run
action(*argument)
TypeError: 'NoneType' object is not callable
I was wondering if anyone could lend their expertise and inform me what I'm doing wrong. I'm still a beginner in python, but this isn't the first program I have made.
You register the return value of service_info(); that function returns None.
If you wanted service_info() to be called by the scheduler instead, you'll need to register the reference to the function itself, together with a tuple of arguments:
run_periodically(time()+5, time()+10, 1, service_info, (action, machine, service))
and adjust run_periodically() to accept the arguments and pass that on to the scheduler.enterabs() method:
def run_periodically(start, end, interval, func, args=()):
event_time = start
while event_time < end:
s.enterabs(event_time, 0, func, args)
event_time += interval
s.run()