Error when analyzing position with Stockfish engine in Python - python

I am trying to retrieve the evaluation scores of each move from the perspective of white in a PGN file by analyzing the positions using the Stockfish chess engine in Python. I am using the python-chess library to interact with the Stockfish engine.
I am running into an error when trying to analyze the position with the Stockfish engine. The error message is "object NoneType can't be used in 'await' expression" which suggests that something in the expression await engine._position(board) is returning None which is not a valid object for the await statement.
Here's my minimal reporducible example:
import chess
import chess.pgn
import chess.engine
import logging
import asyncio
import numpy as np
logging.basicConfig(filename='debug.log', level=logging.DEBUG)
file_path = r"C:\Users\iftik\Downloads\libase\New folder\ex_game.pgn"
stockfish = r"C:\Users\iftik\Downloads\stockfish\stockfish-windows-2022-x86-64-avx2.exe"
async def get_eval(file_path):
"""
Function that retrieves the evaluation scores of each move in a PGN file
by analyzing the position using Stockfish chess engine.
"""
# create an empty numpy array to store evaluation scores
evaluation_scores = np.array([])
board = chess.Board()
transport, engine = await chess.engine.popen_uci(stockfish)
try:
with open(file_path, 'r') as file:
game = chess.pgn.read_game(file)
# iterate through every move in the game
for move in game.mainline_moves():
# make the move on the board
board.push(move)
await engine._position(board)
with await engine.analysis(board) as analysis:
async for info in analysis:
# don't stop until analysis reaches depth 30
if info.get("seldepth", 0) > 30:
evaluation_scores = np.append(evaluation_scores, info.get("score").white().cp)
break
#undo the move
board.pop()
except Exception as e:
logging.error("An error occurred while analyzing position: %s", e)
finally:
await engine.quit()
return evaluation_scores
async def main():
position_evaluations = await get_eval(file_path)
print(position_evaluations)
asyncio.run(main())
I have tried using a try-except block to handle any errors that occur during the analysis and logging the error message using the logging module. But the error still persists.
I was expecting to be able to analyze the position and retrieve the evaluation scores without any errors. However, the error "object NoneType can't be used in 'await' expression" is preventing me from doing so.
I've looked at communicate with stockfish with python and How to Communicate with a Chess engine in Python? and will soon try this to interact with the engine using python stockfish module as suggested by Pranav Hosangadi
. I've also look at UCI/XBoard engine communication:Analysing and evaluating a position , but it doesn't talk about analyzing the position for moves I already have based on a game that's already been played in the documentation.
I am looking for any suggestions on how to fix this error and successfully analyze the position with the Stockfish engine. After writing this post I am now thinking about how would I use stockfish.make_moves_from_curent_position() (from stockfish import Stockfish) or stockfish.set_position() from (from stockfish import Stockfish) to retrieve the evaluation scores of each move in a PGN file from the perspective of white. Any help on the logic would be great considering the time I took to write the post.
Here's the the debugging log output from my actual code -- not the minimal reporducible example:
DEBUG:asyncio:Using proactor: IocpProactor
DEBUG:root:Starting main function
DEBUG:root:Getting evaluation scores
DEBUG:root:Opening file
DEBUG:root:Starting iteration over moves
DEBUG:root:Starting Stockfish
DEBUG:chess.engine:<UciProtocol (pid=6840)>: Connection made
DEBUG:chess.engine:<UciProtocol (pid=6840)>: << uci
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> Stockfish 15.1 by the Stockfish developers (see AUTHORS file)
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> id name Stockfish 15.1
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> id author the Stockfish developers (see AUTHORS file)
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >>
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Debug Log File type string default
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Threads type spin default 1 min 1 max 1024
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Hash type spin default 16 min 1 max 33554432
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Clear Hash type button
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Ponder type check default false
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name MultiPV type spin default 1 min 1 max 500
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Skill Level type spin default 20 min 0 max 20
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Move Overhead type spin default 10 min 0 max 5000
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Slow Mover type spin default 100 min 10 max 1000
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name nodestime type spin default 0 min 0 max 10000
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name UCI_Chess960 type check default false
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name UCI_AnalyseMode type check default false
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name UCI_LimitStrength type check default false
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name UCI_Elo type spin default 1350 min 1350 max 2850
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name UCI_ShowWDL type check default false
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name SyzygyPath type string default <empty>
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name SyzygyProbeDepth type spin default 1 min 1 max 100
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Syzygy50MoveRule type check default true
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name SyzygyProbeLimit type spin default 7 min 0 max 7
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name Use NNUE type check default true
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> option name EvalFile type string default nn-ad9b42354671.nnue
DEBUG:chess.engine:<UciProtocol (pid=6840)>: >> uciok
DEBUG:root:Setting position
DEBUG:chess.engine:<UciProtocol (pid=6840)>: << position startpos moves e2e4
ERROR:root:An error occurred while analyzing position: object NoneType can't be used in 'await' expression
DEBUG:root:Closing Stockfish
DEBUG:chess.engine:<UciProtocol (pid=6840)>: << quit
DEBUG:chess.engine:<UciProtocol (pid=6840)>: Process exited
DEBUG:chess.engine:<UciProtocol (pid=6840)>: Connection lost (exit code: 0, error: None)
DEBUG:root:Starting Stockfish
'''

Related

bitcoinlib scan() or utxos_update() causing bitcoin wallet to stall using Godot Game Engine and python via PythonScript addon by Touilleman

As the title states, the wallet I am creating works perfectly using bitcoinlib library until I have to update the unspent transactions (update the balance). When the w.scan() or w.utxo_update() is called the program freezes and no input boxes or buttons can be used while the process takes place (if you click on the program while it is in this state, windows declares it as "not responding") and sometimes that takes up to a minute. I am trying to call these functions in the _process() function in Godot to update every 30 seconds or so, so the balance stays up to date.
Code wise, my wallet.gd would be something like this
func _process(delta):
process_count += 1
custom_multiplayer.poll()
if process_count >= 1000:
get_node('../Python').scan_wallet()
process_count = 0
Then in Python.py would be
import bitcoinlib
#exposed
class Python(Node):
def scan_wallet(self):
w = self.get_wallet() # gets the wallet in db set by bitcoinlib
w.scan()
w.utxos_update()
Any help to stop this behavior would be appreciated!

pyttsx3 prints the current word being uttered

i basically want the tts to talk while printing out what it is saying.
i'v pretty much copied and pasted the pyttsx3 documentation to do this but it just would not work.
import pyttsx3
def onStart(name):
print ('starting', name)
def onWord(name, location, length):
print ('word', name, location, length)
def onEnd(name, completed):
print ('finishing', name, completed)
engine = pyttsx3.init()
engine.connect('started-utterance', onStart)
engine.connect('started-word', onWord)
engine.connect('finished-utterance', onEnd)
engine.say('The quick brown fox jumped over the lazy dog.')
engine.runAndWait()
and the result is this. the word event only fires after the speaking was complete and none of the words are actually printed.
starting None
word None 1 0
finishing None True
iv been working on this for days, iv tried other libraries like win32com.client.Dispatch('SAPI.Spvoice') and gtts, but none seems to be able to do what I want. Sapi.spvoice seems to have an event which would do what I want it, but I cant seem to get that to work either. though I'm not sure I'm doing it correctly either. https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms723593(v=vs.85)
from win32com.client import Dispatch
import win32com.client
class ContextEvents():
def onWord():
print("the word event occured")
# Work with Result
s = Dispatch('SAPI.Spvoice')
e = win32com.client.WithEvents(s, ContextEvents)
s.Speak('The quick brown fox jumped over the lazy dog.')
from what I understood, there needs to be a class for the events and the event must in the form of On(event) in that class. or something.
i tried installing espeak but that did not work out either.
keep in mined I'm kinda of a newb in python so if anyone would be willing to give a thorough explination that would be really great.
So I'm not familiar with that library, but most likely what's happening is the stream is getting generated and played before the events are able to be passed off to the wrapper library. I can say that AWS's Polly will output word-level timing information if you want to use that - you'd need two calls - one to get the audio stream and the other to get the ssml metadata.
The Windows .net System.Speech.Synthesis library does have progress events that you could listen for, but I don't know if there's a python library to wrap that.
However, if you're willing to run a powershell command from python then you can try using this gist I wrote, which wraps the Windows synthesis functionality and outputs the word timings. Here's an example that should get you what you want:
$text = "hello world! this is a long sentence with many words";
$sampleRate = 24000;
# generate tts and save bytes to memory (powershell variable)
# events holds event timings
# NOTE: assumes out-ssml-winrt.ps1 is in current directory, change as needed...
$events = .\out-ssml-winrt.ps1 $text -Variable 'soundstream' -SampleRate $sampleRate -Channels 1 -SpeechMarkTypes 'words';
# estimate duration based on samplerate (rough)
$estimatedDurationMilliseconds = $global:soundstream.Length / $sampleRate * 1000;
$global:e = $events;
# add a final event at the end of the loop to wait for audio to complete
$events += #([pscustomobject]#{ type = 'end'; time = $estimatedDurationMilliseconds; value = '' });
# create background player
$memstream = [System.IO.MemoryStream]::new($global:soundstream);
$player = [System.Media.SoundPlayer]::new($memstream)
$player.Play();
# loop through word events
$now = 0;
$events | % {
$word = $_;
# milliseconds into wav file event happens
$when = $word.time;
# distance from last timestamp to this event
$delta = $when - $now;
# wait until right time to display
if ($delta -gt 0) {
Start-sleep -Milliseconds $delta;
}
$now = $when;
# output word
Write-Output $word.value;
}
# just to let you know - audio should be finished
Write-Output "Playback Complete";
$player.Stop(); $player.Dispose(); $memstream.Dispose();

How to use python to read and write a register via LLDB?

I'm trying to use python to read/write a register when it hits the breakpoint.
I was able to execute a simple python script when a breakpoint is triggered.
The problem I'm having is reading and writing a single register. I can get a list of registers, but not a register.
* thread #1, stop reason = signal SIGSTOP
frame #0: 0x000000010521562c dyld` ImageLoaderMachO::usablePrebinding(ImageLoader::LinkContext const&) const + 56
dyld`ImageLoaderMachO::usablePrebinding:
-> 0x10521562c <+56>: ldrb w8, [x19, #0x76]
0x105215630 <+60>: ldrh w9, [x19, #0x74]
0x105215634 <+64>: bfi w9, w8, #16, #8
0x105215638 <+68>: tbz w9, #0x9, 0x105215694 ; <+160>
0x10521563c <+72>: ldr x8, [x19]
0x105215640 <+76>: ldr x8, [x8, #0x378]
0x105215644 <+80>: mov x0, x19
0x105215648 <+84>: blr x8
Target 0: (BBM) stopped.
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> print lldb.frame.registers
Can anyone help me which python api I can use to change the x1 register value?
The registers property on SBFrames is an SBValueList that stores the sets of registers (GPR's, etc.). Each register set is an SBValue, and the individual registers are represented as children of the register set, with the child name being the register name. x1 is a GPR, and the GPR's are always the first register set in registers. SBValueList also GetFirstValueByName to get an element by name, so you can also find the "General Purpose Register"'s programmatically.
So you would do something like:
error = lldb.SBError()
did_change = lldb.frame.registers[0].GetChildMemberWithName('x1').SetValueFromCString("0x12345",error)
SetValueFromCString returns True if it was able to change the value, and if it wasn't, the reason why will be stored in the error parameter.
Note that volatile registers like x1 aren't stored across function calls, so you can only access or change their values in the currently executing frame.
SBValues are described here:
https://lldb.llvm.org/python_reference/lldb.SBValue-class.html
if you want to know what else you can do with them.
An alternative to the registers property, is the register property. It's a convenience for accessing registers by name. For example:
(lldb) script print lldb.frame.register["x1"].value
(lldb) script lldb.frame.register["x1"].value = "0"
#Dave Lee's answer worked in the script interface of lldb.
When I tried the same in a full script, I was getting null register values.
The documentation https://lldb.llvm.org/use/python-reference.html explained all. You needed to pass in exe_ctx to get the correct context. This was the lldb.SBExecutionContext.
def YDFooBarFunction(debugger, command, exe_ctx, result, internal_dict):
"""
Reads and writes a register.
"""
frame = exe_ctx.frame
error = lldb.SBError()
disposition = frame.FindRegister("rsi")
print("[*]Original register: " + str(disposition))
if disposition.unsigned == 2:
print "[!]found 2 in the register"
result = frame.registers[0].GetChildMemberWithName('rsi').SetValueFromCString("0x1", error)
messages = {None: 'error', True: 'pass', False: 'fail'}
print ("[*]PATCHING result: " + messages[result])
thread = frame.GetThread()
process = thread.GetProcess()
process.Continue()
I hope this saves people hours of hunting.
Note, I used part of the great man's ( #Jim Ingham's ) answer to write a register.

Checking STOP time of EC2 instance with boto3

Python 2.7
Boto3
I'm trying to get a timestamp of when the instance was stopped OR the time the last state transition took place OR a duration of how long the instance has been in the current state.
My goal is to test if an instance has been stopped for x hours.
For example,
instance = ec2.Instance('myinstanceID')
if int(instance.state['Code']) == 80:
stop_time = instance.state_change_time() #Dummy method.
Or something similar to that.
I see that boto3 has a launch_time method. And lots of ways to analyze state changes using state_transition_reason and state_reason but I'm not seeing anything regarding the state transition timestamp.
I've got to be missing something.
Here is the Boto3 docs for Instance "state" methods...
state
(dict) --
The current state of the instance.
Code (integer) --
The low byte represents the state. The high byte is an opaque internal value and should be ignored.
0 : pending
16 : running
32 : shutting-down
48 : terminated
64 : stopping
80 : stopped
Name (string) --
The current state of the instance.
state_reason
(dict) --
The reason for the most recent state transition.
Code (string) --
The reason code for the state change.
Message (string) --
The message for the state change.
Server.SpotInstanceTermination : A Spot instance was terminated due to an increase in the market price.
Server.InternalError : An internal error occurred during instance launch, resulting in termination.
Server.InsufficientInstanceCapacity : There was insufficient instance capacity to satisfy the launch request.
Client.InternalError : A client error caused the instance to terminate on launch.
Client.InstanceInitiatedShutdown : The instance was shut down using the shutdown -h command from the instance.
Client.UserInitiatedShutdown : The instance was shut down using the Amazon EC2 API.
Client.VolumeLimitExceeded : The limit on the number of EBS volumes or total storage was exceeded. Decrease usage or request an increase in your limits.
Client.InvalidSnapshot.NotFound : The specified snapshot was not found.
state_transition_reason
(string) --
The reason for the most recent state transition. This might be an empty string.
The EC2 instance has an attribute StateTransitionReason which also has the time the transition happened. Use Boto3 to get the time the instance was stopped.
print status['StateTransitionReason']
...
User initiated (2016-06-23 23:39:15 GMT)
The code below prints stopped time and current time. Use Python to parse the time and find the difference. Not very difficult if you know Python.
import boto3
import re
client = boto3.client('ec2')
rsp = client.describe_instances(InstanceIds=['i-03ad1f27'])
if rsp:
status = rsp['Reservations'][0]['Instances'][0]
if status['State']['Name'] == 'stopped':
stopped_reason = status['StateTransitionReason']
current_time = rsp['ResponseMetadata']['HTTPHeaders']['date']
stopped_time = re.findall('.*\((.*)\)', stopped_reason)[0]
print 'Stopped time:', stopped_time
print 'Current time:', current_time
Output
Stopped time: 2016-06-23 23:39:15 GMT
Current time: Tue, 20 Dec 2016 20:33:22 GMT
You might consider using AWS Config to view the configuration history of the instances.
AWS Config is a fully managed service that provides you with an AWS resource inventory, configuration history, and configuration change notifications to enable security and governance
The get-resource-config-history command can return information about an instance, so it probably has Stop & Start times. It will take a bit of parsing to extract the details.

Handling time-out for Python-script with RS485 & minimalmodbus

Presently have a read-out on an RS485-bus of 1 (one) RS485 kWh-meter, type DDS238-1ZN by means of a Python-script 'assisted' by module minimalmodbus.
Adding more kWh-meters means that (prior or during installation) the Slave-Adress of the added kWh-meter has to be shifted from the initial '1'.
Such shift-action starts with scanning the RS485-bus to determine where kWh-meter(s) are actually located.
First step is the following simple Python-script
import serial
import minimalmodbus
# Check address 00 = broadcast
instrument = minimalmodbus.Instrument('/dev/ttyAMA0',0) # port name, slave address
instrument.serial.baudrate = 9600
instrument.serial.timeout = 0.5
instrument.debug = True
print instrument
print instrument.read_register(21,0) # registernumber, number of decimals
# Check address 01 = slave 01
instrument = minimalmodbus.Instrument('/dev/ttyAMA0',1) # port name, slave address
print instrument
print instrument.read_register(21,0) # registernumber, number of decimals
# Check address 02 = slave02
instrument = minimalmodbus.Instrument('/dev/ttyAMA0',2) # port name, slave address
print instrument
print instrument.read_register(21,0) # registernumber, number of decimals
The check on Slave-addresses 00 and 01 produces the result (257) as expected, but (due to absence of a device) obviously response on Slave-adress 02 is failing with a time-out.
For further problem-description see http://www.domoticz.com/forum/viewtopic.php?f=31&t=13592#p102901
From test runs, I can see that a time-out occurs.
A time-out-signal could be trigger to step-over to check for next slave-address, if I knew the layout of such time-out-signal for a Python-script with minimalmodbus ....
Searching the internet for an alternative, I see all kind of 'wonderful &elaborate' solutions to trap a time-out, but in the perspective of my simple script I am looking for something very basic (preferably a 'one-liner') to enable stepping out of the time-out to check the next slave-address 3, etc.
Looking at those solutions mentioned above, could perhaps the following setup with semi-code be a simple/basic solution? [for which I have been looking in direction of the C-function fread() ]
start of loop
start time-counter
read register from slave address x
N = number of characters received
if time-counter at value t, then
look if N > 0
if N == 0 then
x = x + 1
jump to start of loop
Any hint for a script using Python or MinimalModbus to perform the semi-code, compatible with the first script?
No working solution found/received in this Forum, but a pragmatic, simple remedy has been developed, tested and put in action, as described at http://www.domoticz.com/forum/viewtopic.php?f=14&t=5808&start=20#p113697
Due to the characteristics of it's data-protocol, the remedy is specific for kWh-meter type DDS238-1ZN, but the idea can possibly be applied for other, comparable kWh-meters with RS485-interface.

Categories