Every time I run this script on my Raspberry Pi:
import curses
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
motor1a = 7
motor1b = 11
motor1e = 22
motor2a = 13
motor2b = 16
motor2e = 15
GPIO.setup(motor1a,GPIO.OUT)
GPIO.setup(motor1b,GPIO.OUT)
GPIO.setup(motor1e,GPIO.OUT)
GPIO.setup(motor2a,GPIO.OUT)
GPIO.setup(motor2b,GPIO.OUT)
GPIO.setup(motor2e,GPIO.OUT)
screen = curses.initscr()
curses.noecho()
curses.cbreak()
curses.halfdelay(3)
screen.keypad(True)
try:
while True:
char = screen.getch()
if char == ord('q'):
break
elif char == curses.KEY_UP:
GPIO.output(motor1a,GPIO.HIGH)
GPIO.output(motor1b,GPIO.LOW)
GPIO.output(motor1e,GPIO.HIGH)
GPIO.output(motor2a,GPIO.HIGH)
GPIO.output(motor2b,GPIO.LOW)
GPIO.output(motor2e,GPIO.HIGH)
# except SOMEEXCEPTION is missing here, I am not sure why there is an exception in the first place
I get an error:
_curses.error: setupterm: could not find terminal
How can I fix this?
I saw a post where it said to do the following:
You must set environment variables TERM and TERMINFO, like this:
export TERM=linux ; export TERMINFO=/etc/terminfo
But I'm not sure where to do that step.
In order to use curses, you need to tell which terminal you are using so that the library can send correct commands. This is done by running the commands you provided in a shell, at the same place where you run your program
$ export TERM=linux
$ export TERMINFO=/etc/terminfo
$ python3 myprogram.py
($ is the prompt of the shell, you may have something else)
As I mentioned in my comment, your code will not run anyway, there is an except missing after the try (I am not sure what you need the try for, and you will need to understand this anyway in order to catch the right exception)
Related
I am able to symbolicate symbol address through following lldb command:
image lookup --address $SYMBOL_ADDRRESS
But while writing a shell script to parse, I am not able to find a way to store the output of above command into a variable or file.
First off, if your script's job is mostly about driving lldb and you happen to know Python, you will be much happier using the lldb module in Python, where you can drive the debugger directly, than getting lldb to produce text output which you parse in the shell script.
The lldb Python module provides API's like SBTarget.ResolveSymbolContextForAddress, which runs the same lookup as image lookup --address but returns the result as a Python lldb.SBSymbolContext object, which you can either query for module/file/line etc using API's on the object. So getting bits of info out of this result will be easier with the lldd API's.
But if you have to use a shell script, then the easiest thing is probably to write the command output to a file and read that back into the shell script. lldb doesn't have generic support for tee-ing command output into a log file yet, but the lldb Python module allows you to run command-line commands and programmatically capture the output.
So you can do it easily from lldb's Python script interpreter:
(lldb) script
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
>>> result = lldb.SBCommandReturnObject()
>>> lldb.debugger.GetCommandInterpreter().HandleCommand("image lookup -va $pc", result)
2
>>> fh = open("/tmp/out.txt", "w")
>>> fh.write(result.GetOutput())
>>> fh.close()
>>> quit
(lldb) plat shell cat /tmp/out.txt
Address: foo[0x0000000100003f6f] (foo.__TEXT.__text + 15)
Summary: foo`main + 15 at foo.c:6:3
Module: file = "/tmp/foo", arch = "x86_64"
CompileUnit: id = {0x00000000}, file = "/tmp/foo.c", language = "c99"
Function: id = {0x7fffffff00000032}, name = "main", range = [0x0000000100003f60-0x0000000100003f8a)
FuncType: id = {0x7fffffff00000032}, byte-size = 0, decl = foo.c:4, compiler_type = "int (void)"
Blocks: id = {0x7fffffff00000032}, range = [0x100003f60-0x100003f8a)
LineEntry: [0x0000000100003f6f-0x0000000100003f82): /tmp/foo.c:6:3
Symbol: id = {0x00000005}, range = [0x0000000100003f60-0x0000000100003f8a), name="main"
You can also write a lldb command in Python that wraps this bit of business, which would make it easier to use. Details on that are here:
https://lldb.llvm.org/use/python-reference.html#create-a-new-lldb-command-using-a-python-function
You could even do a hybrid approach, and make all the lldb work you want to do a custom Python command. That would allow you to use the lldb Python API's to get what info you needed and write it out in whatever format is convenient for you, and would simplify the lldb invocation in your shell script and facilitate recovering the information lldb provided...
I basically try to run the example 3.11 in Odersky's book (Programming in Scala). I am using Intellij IDE. While runing the code, the "else" branch got executed.
The screen capture is here:
The source is here in case you need it to try:
package ch3
import scala.io.Source
object l3p11 extends App{
def widthOfLength(s: String) = s.length.toString.length
if (args.length > 0){
val lines = Source.fromFile(args(0)).getLines().toList
val longestLine = lines.reduceLeft(
(a, b) => if (a.length > b.length) a else b
)
val maxWidth = widthOfLength(longestLine)
for (line <- lines){
val numSpaces = maxWidth - widthOfLength(line)
val padding = " " * numSpaces
println(padding + line.length + "|" + line)
}
}
else
Console.err.println("Please enter filename")
}
The reason, I think, is becuase I did not pass args correctly (say here I want to pass the source file l3p11.scala as the args). I tried several option, but have not find a way to pass the args correctly for the code to be executed in the "if" branch. There are two directions in my mind to resolve this problem:
1. Find the right way to pass args in Intellij IDE
Run Scala in commond line, a similar command such as
$ scala l3p11.scala l3p11.scala
should be able to pass the args correctly. But my current setting gives "bash: scala: command not found". I currently use scala REPL to run scala code following the set up given in Odersky's Coursera course on Scala. I think I need to change the set up in orde run scala directly, instead of using "sbt->console" to invoke the scala interpreter like what I am doing now.
Any suggestion on either direction (or other directions that I have not thought of) to resolve the problem is welcome.
Update 1:
Direction 2 works after I reinstall scala. (My to be corrected understanding is that the installation of sbt does not provide an executable binary of scala to be included in the environment list for Windows. Therefore, scala command cannot be found before). After installation of scala directly:
$ scala l3p11.scala l3p11.scala
gives the expected results. But I still have not figured out how to get this result with Intellij IDEA.
Update 2:
I revisited the "Program arguments" option after Joe's confirmation. The reason I was not be able to get it work before was that I only add "l3p11.scala". Adding the complete path from working directory "src/main/scala/ch3/l3p11.scala" solved the problem. The result is as following:
To pass command-line arguments when running a program in IntelliJ IDEA, use the "Edit Configurations …" menu item under "Run". Choose the entry for your main program. There's a "Program arguments" text field where you specify the arguments to pass to the program.
I'm not super familiar on how it will run on windows but if you are able to run it directly from the command line then I think you'll need to compile first, that's the scalac command. So:
$ scalac l3p11.scala
then you can run just with the class name, not sure if you would need quotes on the arg:
$ scala l3p11 l3p11.scala
The idea of the following was to use Bash's select from Python, e.g. use Bash select to get the input from the user, communicate with the Bash script to get the user selections and use it afterwords in the Python code. Please tell me if it at least possible.
Have the following simple Bash script:
#!/bin/bash -x
function select_target {
target_list=("Target1" "Target2" "Target3")
PS3="Select Target: "
select target in "${target_list[#]}"; do
break
done
echo $target
}
select_target
it works standalone
Now I tried to call it from Python like this:
import tempfile
import subprocess
select_target_sh_func = """
#!/bin/bash
function select_target {
target_list=(%s)
PS3="Select Target: "
select target in "${target_list[#]}"; do
break
done
echo $target
}
select_target
"""
target_list = ["Target1", "Target2", "Target3"]
with tempfile.NamedTemporaryFile() as temp:
temp.write(select_target_sh_func % ' '.join(map(lambda s : '\"%s\"' % str(s),target_list)))
subprocess.call(['chmod', '0777', temp.name])
sh_proc = subprocess.Popen(["bash", temp.name], stdout=subprocess.PIPE)
(output, err) = sh_proc.communicate()
exit_code = sh_proc.wait()
print output
It does nothing. No output, no selection.
I'm using High Sierra MacOS, PyCharm and Python 2.7.
PS
After some reading and experimenting ended up with the following:
with tempfile.NamedTemporaryFile() as temp:
temp.write(select_target_sh_func % ' '.join(map(lambda s : '\"%s\"' % str(s),target_list)))
temp.flush()
# bash: /var/folders/jm/4j4mq_w52bx2l5qwg4gt44580000gn/T/tmp00laDV: Permission denied
subprocess.call(['chmod', '0500', temp.name])
sh_proc = subprocess.Popen(["bash", "-c", temp.name], stdout=subprocess.PIPE)
(output, err) = sh_proc.communicate()
exit_code = sh_proc.wait()
print output
It behaves as I expected it would, the user is able to select the 'target' by just typing the number. My mistake was that I forgot to flush.
PPS
The solution works for MacOS X High Sierra, sadly it does not for Debian Jessie complaining the following:
bash: /tmp/tmpdTv4hp: Text file busy
I believe it is because `with tempfile.NamedTemporaryFile' keeps the temp file open and this somehow prevents Bash from working with it. This renders the whole idea useless.
Python is sitting between your terminal or console and the (noninteractive!) Bash process you are starting. Furthermore, you are failing to direct the standard output pipe anywhere, so subprocess.communicate() actually cannot capture standard error (and if it could, you would not be able to see the script's menu).
Running an interactive process programmatically is a nontrivial scenario; you'll want to look at pexpect or just implement your own select command in Python - I suspect this is going to turn out to be the easiest solution (trivially so if you can find an existing library).
I am trying to work out how to setup a Shell to run as a cron, I have created a TaskEmailerShell.php file at /app/Console/Command/TaskEmailerShell.php with the following code:
App::uses('CakeEmail', 'Network/Email');
class TaskEmailerShell extends AppShell {
public $uses = array('Task');
public function main()
{
// GENERATE AND SEND THE EMAIL
// ------------------------------------------------------------>
$email = new CakeEmail();
etc etc
I have followed the instructions here and when the cron runs I get this error:
/home/village/public_html/app/Console/cakeshell: line 14: cake: command not found
My cron command is:
/home/village/public_html/app/Console/cakeshell TaskEmailer -cli /usr/bin -console /Cake/Console -app /home/village/public_html/app >> /home/village/public_html/emailer_log.log
Any suggestions where I am going wrong?
The cakeshell script you're referring to there requires the cake console binary to be somewhere in PATH, or (at least from looking at the usage example), for you to have specified the full path to the Console with the -console argument. It looks like you've got a relative path there.
Personally I recommend just calling the cake console directly from your cron job. As other needs arise you may end up writing a script like cakeshell to wrap the console. You could try something like :
# m h dom mon dow command
*/5 * * * * /home/village/public_html/lib/Cake/Console/cake -app '/home/village/public_html/app/' TaskEmailer >> /home/village/public_html/emailer_log.log
Command not found usually means your PATH is the problem. Programs run from cron might not even have PATH set. Any script started by cron must set PATH near the beginning or it won't find any of the programs it is supposed to run.
The error occurs at line 14 in the file cakeshell: $cmd. cmd is set at line 4.
#!/bin/bash
TERM=dumb
export TERM
cmd="/opt/lampp/htdocs/MyApp/app/Console/cake"
while [ $# -ne 0 ]; do
if [ "$1" = "-cli" ] || [ "$1" = "-console" ]; then
PATH=$PATH:$2
shift
else
cmd="${cmd} $1"
fi
shift
done
$cmd
Originally line 4 is
cmd="cake"
Change it to absolute path like:
cmd="/opt/lampp/htdocs/MyApp/app/Console/cake"
where MyApp is the application directory. I have faced this problem even after PATH settings. Then mentioning the absolute path solved it.
This example routine generates two Throw::nocatch warning messages in the kernel window. Can they be handled somehow?
The example consists of this code in a file "test.m" created in C:\Temp:
Needs["JLink`"];
$FrontEndLaunchCommand = "Mathematica.exe";
UseFrontEnd[NotebookWrite[CreateDocument[], "Testing"]];
Then these commands pasted and run at the Windows Command Prompt:
PATH = C:\Program Files\Wolfram Research\Mathematica\8.0\;%PATH%
start MathKernel -noprompt -initfile "C:\Temp\test.m"
Addendum
The reason for using UseFrontEnd as opposed to UsingFrontEnd is that an interactive front end may be required to preserve output and messages from notebooks that are usually run interactively. For example, with C:\Temp\test.m modified like so:
Needs["JLink`"];
$FrontEndLaunchCommand="Mathematica.exe";
UseFrontEnd[
nb = NotebookOpen["C:\\Temp\\run.nb"];
SelectionMove[nb, Next, Cell];
SelectionEvaluate[nb];
];
Pause[10];
CloseFrontEnd[];
and a notebook C:\Temp\run.nb created with a single cell containing:
x1 = 0; While[x1 < 1000000,
If[Mod[x1, 100000] == 0,
Print["x1=" <> ToString[x1]]]; x1++];
NotebookSave[EvaluationNotebook[]];
NotebookClose[EvaluationNotebook[]];
this code, launched from a Windows Command Prompt, will run interactively and save its output. This is not possible to achieve using UsingFrontEnd or MathKernel -script "C:\Temp\test.m".
During the initialization, the kernel code is in a mode which prevents aborts.
Throw/Catch are implemented with Abort, therefore they do not work during initialization.
A simple example that shows the problem is to put this in your test.m file:
Catch[Throw[test]];
Similarly, functions like TimeConstrained, MemoryConstrained, Break, the Trace family, Abort and those that depend upon it (like certain data paclets) will have problems like this during initialization.
A possible solution to your problem might be to consider the -script option:
math.exe -script test.m
Also, note that in version 8 there is a documented function called UsingFrontEnd, which does what UseFrontEnd did, but is auto-configured, so this:
Needs["JLink`"];
UsingFrontEnd[NotebookWrite[CreateDocument[], "Testing"]];
should be all you need in your test.m file.
See also: Mathematica Scripts
Addendum
One possible solution to use the -script and UsingFrontEnd is to use the 'run.m script
included below. This does require setting up a 'Test' kernel in the kernel configuration options (basically a clone of the 'Local' kernel settings).
The script includes two utility functions, NotebookEvaluatingQ and NotebookPauseForEvaluation, which help the script to wait for the client notebook to finish evaluating before saving it. The upside of this approach is that all the evaluation control code is in the 'run.m' script, so the client notebook does not need to have a NotebookSave[EvaluationNotebook[]] statement at the end.
NotebookPauseForEvaluation[nb_] := Module[{},While[NotebookEvaluatingQ[nb],Pause[.25]]]
NotebookEvaluatingQ[nb_]:=Module[{},
SelectionMove[nb,All,Notebook];
Or##Map["Evaluating"/.#&,Developer`CellInformation[nb]]
]
UsingFrontEnd[
nb = NotebookOpen["c:\\users\\arnoudb\\run.nb"];
SetOptions[nb,Evaluator->"Test"];
SelectionMove[nb,All,Notebook];
SelectionEvaluate[nb];
NotebookPauseForEvaluation[nb];
NotebookSave[nb];
]
I hope this is useful in some way to you. It could use a few more improvements like resetting the notebook's kernel to its original and closing the notebook after saving it,
but this code should work for this particular purpose.
On a side note, I tried one other approach, using this:
UsingFrontEnd[ NotebookEvaluate[ "c:\\users\\arnoudb\\run.nb", InsertResults->True ] ]
But this is kicking the kernel terminal session into a dialog mode, which seems like a bug
to me (I'll check into this and get this reported if this is a valid issue).