Pdb error while debugging python app with serverless launched offline - python

I have problem with debugging my view function with
import pdb; pdb.set_trace()
placed inside it and serverless launched as
> sls offline start
in console.
Namely, making correspondent GET request I receive the following error:
Python: > /.../handler.py(88)get_results()
-> request_params = event.query_params
Python: (Pdb)
Python: 2019-02-20 18:37:43,648 [ERROR] | ...
Traceback (most recent call last):
...
File ".../handler.py", line 88, in get_results
...
File "/usr/lib/python3.6/bdb.py", line 51, in trace_dispatch
return self.dispatch_line(frame)
File "/usr/lib/python3.6/bdb.py", line 70, in dispatch_line
if self.quitting: raise BdbQuit
bdb.BdbQuit
Google suggests that the problem is in the inability of serverless process to read from stdin, but I don't know how to handle this problem.
Any suggestions?

I found a solution here https://stackoverflow.com/a/26975795/4388451:
create two fifos:
mkfifo fifo_stdin
mkfifo fifo_stdout
in one terminal
In the same terminal open stdout on background, and write to stdin:
cat fifo_stdout & cat > fifo_stdin
In python code create the the pdb object, and use it:
import pdb
mypdb = pdb.Pdb(stdin=open('fifo_stdin', 'r'), stdout=open('fifo_stdout', 'w'))
....
mypdb.set_trace()
Run python code from the folder where fifos were placed (or place fifos in the first step in the folder with python code) in another terminal
Now I am able to use pdb in first console!
PS
It is useful to use --noTimeout option while debugging: sls offline --noTimeout

Related

servable panel app ModuleNotFoundError on included local module

I'm having issues deploying my Panel app to be served up as HTML.
Following instructions at https://panel.holoviz.org/user_guide/Running_in_Webassembly.html, with script.py as
import panel as pn
from mymodule import MyObj
pn.extension('terminal', 'tabulator', sizing_mode="stretch_width")
gspec = pn.GridSpec(sizing_mode='stretch_width', max_height=100, ncols=3)
PI = MyObj()
gspec[0, 0:1] = PI.tabs
gspec[0, 2] = PI.view
pn.Column(
"Text Text Text"
, gspec
).servable()
and mymodule/__init__.py:
__version__ = '0.1.0'
from .my_obj import MyObj
and mymodule/my_obj.py:
from .param_classes import ClassA
from .param_classes import ClassB
# etc
from .compute_obj import ComputeObj
class MyObj(object):
# all the details of the panel build, calling in turn
# param classes detailed in another file, and also calling another module
# to handle all the computation behind the panel
panel serve script.py --autoreload works perfectly, but
$ panel convert script.py --to pyodide-worker --out pyodide
$ python3 -m http.server
does not work. I get a big display at http://localhost:8000/pyodide/script.html: ModuleNotFoundError: no module named 'mymodule', and an infinite loop spinning graphic, and in the Developer Tools Console output:
pyodide.asm.js:10 Uncaught (in promise) PythonError: Traceback (most recent call last):
File "/lib/python3.10/asyncio/futures.py", line 201, in result
raise self._exception
File "/lib/python3.10/asyncio/tasks.py", line 232, in __step
result = coro.send(None)
File "/lib/python3.10/site-packages/_pyodide/_base.py", line 506, in eval_code_async
await CodeRunner(
File "/lib/python3.10/site-packages/_pyodide/_base.py", line 359, in run_async
await coroutine
File "<exec>", line 11, in <module>
ModuleNotFoundError: No module named 'mymodule'
at new_error (pyodide.asm.js:10:218123)
at pyodide.asm.wasm:0xdef7c
at pyodide.asm.wasm:0xe37ae
at method_call_trampoline (pyodide.asm.js:10:218037)
at pyodide.asm.wasm:0x126317
at pyodide.asm.wasm:0x1f6f2e
at pyodide.asm.wasm:0x161a32
at pyodide.asm.wasm:0x126827
at pyodide.asm.wasm:0x126921
at pyodide.asm.wasm:0x1269c4
at pyodide.asm.wasm:0x1e0697
at pyodide.asm.wasm:0x1da6a5
at pyodide.asm.wasm:0x126a07
at pyodide.asm.wasm:0x1e248c
at pyodide.asm.wasm:0x1e00d9
at pyodide.asm.wasm:0x1da6a5
at pyodide.asm.wasm:0x126a07
at pyodide.asm.wasm:0xe347a
at Module.callPyObjectKwargs (pyodide.asm.js:10:119064)
at Module.callPyObject (pyodide.asm.js:10:119442)
at wrapper (pyodide.asm.js:10:183746)
I should add that I'm using poetry to manage packages and build the venv, and I'm operating all the above from within the activated .venv (via poetry shell)
I've tried all the tips and tricks around append the local path to sys.path. Looking at the .js file that the convert utility generates, I gather it would work if all the code were in one file, but forcing bad coding practice doesn't sound right.
I imagine there could be some kind of C++ build-style --include argument to panel convert, but there are no man pages, and the closest I can get with online documentation is --requirements ./mymodule, but no joy.
Could anybody please advise?

PHP: calling a python script throws ModuleNotFoundError, calling from terminal works just fine?

I have a script, let's call it /home/pi/somescript.py and when I call it with /bin/python3.7 /home/pi/somescript.py everything works as it should.
Now I'm trying to call from a php script with exec('/bin/python3.7 /home/pi/somescript.py', $output, $ret_code);. This however throws a ModuleNotFoundError.
But when I run the interactive PHP shell and paste the above exec in there, it also works. Am I missing something? What could be the cause of this? How do I fix this?
The relevant part of the python script:
import sys
sys.stderr = sys.stdout # so I get the stacktrace in the $output of the php file
from iso3166 import countries # <- error here
# ...
I'm running a lighttpd server. The PHP file lies in /var/www/html/info.php and I access it via a browser with http://raspberrypi:8080/info.php
The relevant part of the PHP file:
exec('/bin/python3.7 /home/pi/somescript.py', $output, $ret_code);
$data = ["out" => $output];
header('Content-Type: application/json');
echo json_encode($data);
// this way I get the output when in the browser
The stacktrace I get:
Traceback (most recent call last):
File "/home/pi/somescript.py", line 6, in <module>
from iso3166 import countries
ModuleNotFoundError: No module named 'iso3166'

Decoupled process from terminal still outputs Traceback to the terminal

While testing an application I made using a rest api I discovered this behaviour which I don't understand.
Lets start by reproducing a similar error as follows -
In file call.py -
Note that this file has code that manifests itself visually for example a GUI that runs forever. Here I am just showing you a representation and deliberately making it raise an Exception to show you the issue. Making a get request and then trying to parse the result as json will raise a JSONDecodeError.
import requests
from time import sleep
sleep(3)
uri = 'https://google.com'
r = requests.get(uri)
response_dict = r.json()
Since I want to run this as a daemon process, I decouple this process from the terminal that started it using the following trick -
In file start.py -
import subprocess
import sys
subprocess.Popen(["python3", "call.py"])
sys.exit(0)
And then I execute python3 start.py
It apparently decouples the process because if there are no exceptions the visual manifestation runs perfectly.
However in case of an exception I immediately see this output in the terminal, even though I got a new prompt after calling python3 start.py -
$ python3 start.py
$ Traceback (most recent call last):
File "call.py", line 7, in <module>
response_dict = r.json()
File "/home/walker/.local/lib/python3.6/site-packages/requests/models.py", line 896, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python3/dist-packages/simplejson/__init__.py", line 518, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 370, in decode
obj, end = self.raw_decode(s)
File "/usr/lib/python3/dist-packages/simplejson/decoder.py", line 400, in raw_decode
return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Now, I understand that all exceptions MUST be handled in the program itself. And I have done it after this strange issue, but what is not clear to me is why did this happen at all in the first place?
It doesn't happen if I quit the terminal and restart the terminal (the visual manifestation gets stuck in case of a Traceback, and no output on any terminal as expected)
Why is a decoupled process behaving this way?
NOTE: Decoupling is imperative to me. It is imperative that the GUI run as a background or daemon process and that the terminal that spawns it is freed from it.
by "decoupled", I assume you mean you want the stdout/stderr to go to /dev/null? assuming that's what you mean, that's not what you've told your code to do
from the docs:
stdin, stdout and stderr specify the executed program’s standard input, standard output and standard error file handles, respectively. Valid values are PIPE, DEVNULL, an existing file descriptor (a positive integer), an existing file object, and None.
With the default settings of None, no redirection will occur; the child’s file handles will be inherited from the parent.
you therefore probably want to be doing:
from subprocess import Popen, DEVNULL
Popen(["python3", "call.py"], stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL)
based on the OPs comment, I think they might be after a tool like GNU screen or tmux. terminal multiplexers, like these, allow you to create a virtual terminal that you can disconnect from and reconnect to at need. these answers see https://askubuntu.com/a/220880/106239 and https://askubuntu.com/a/8657/106239 have examples for tmux and screen respectively

How could I close Excel file using pywinauto

I'm having a problem that I can't excel file.
I was using swapy+pywinauto.
program export excel file with different name (ex. time..)
I used swapy to close the export excel.
from pywinauto.application import Application
app = Application().Start(cmd_line=u'"C:\\Program Files\\Microsoft Office\\Office14\\EXCEL.EXE" \\dde')
xlmain = app.XLMAIN
xlmain.Wait('ready')
xlmain.Close()
app.Kill_()
but got error below.
Traceback (most recent call last):
File "D:/23007.py", line 54, in <module>
xlmain.Wait('ready')
WaitUntil(timeout, retry_interval, lambda: self.__check_all_conditions(check_method_names))
File "C:\Python35\lib\site-packages\pywinauto\timings.py", line 308, in WaitUntil
raise err
pywinauto.timings.TimeoutError: timed out
Process finished with exit code 1
Why do you use app.XLMAIN? Is the title of window similar to XLMAIN? Usually the title is <file name> - Excel so that pywinauto can handle it so: xlmain = app["<file name> - Excel"].
Obviously Wait('ready') raised an exception because the window with title "XLMAIN" or similar is not found.
Generally I would recommend using pyWin32 standard module win32com.client to work with Excel (through standard COM interface). See the second answer here for example: Driving Excel from Python in Windows

Call custom AutoIt function from python

I found a way to run built in auto it functions from python using the following code
from win32com.client import Dispatch
Auto = Dispatch("AutoItX3.Control")
Auto.Run("notepad.exe", "", 5)
Is there a similar way to call custom methods i.e methods defined in my_AutoIt_File.au3
Say I have a method in this file
Func my_autoit_method
;some code
EndFunc
Is there a way to call this my_autoit_method from python?
From the help file:
AutoIt specific command Line Switches
Form1: AutoIt3.exe [/ErrorStdOut] [/AutoIt3ExecuteScript] file
[params ...]
Execute an AutoIt3 Script File
/ErrorStdOut Allows to redirect fatal error to StdOut which can be captured by an application as Scite editor. This switch can be used with a compiled script.
To execute a standard AutoIt Script File 'myscript.au3', use the command:
'AutoIt3.exe myscript.au3'
Form2: Compiled.exe [/ErrorStdOut] [params ...]
Execute an compiled AutoIt3 Script File produced with Aut2Exe.
Form3: Compiled.exe [/ErrorStdOut] [/AutoIt3ExecuteScript file]
[params ...]
Execute another script file from a compiled AutoIt3 Script File. Then you don't need to fileinstall another copy of AutoIT3.exe in your compiled file.
Form4: AutoIt3.exe [/ErrorStdOut] /AutoIt3ExecuteLine "command line"
Execute one line of code.
To execute a single line of code, use the command:
Run(#AutoItExe & ' /AutoIt3ExecuteLine "MsgBox(0, ''Hello World!'', ''Hi!'')"')
You have to expose your AutoIt Function to other applications. This could be done easily with AutoItObject, which can register an object in the ROT.
The AutoIt Code would be:
#include <AutoItObject.au3>
$oObject = _AutoItObject_Create()
_AutoItObject_RegisterObject($oObject, 'MyVery.CustomApplication')
_AutoItObject_AddMethod($oObject, '_my_custom_function', '_my_custom_function')
While Sleep(100)
WEnd
Func _my_custom_function($oSelf)
MsgBox(0, '', 'AutoIt says Hi')
Exit
EndFunc
The Python Code should be:
from win32com.client import Dispatch
Auto = Dispatch("MyVery.CustomApplication")
Auto._my_custom_function()

Categories