alhazmy13 / serverless-offline-python

Emulate AWS λ and API Gateway locally when developing your Serverless project
MIT License
35 stars 18 forks source link

Attaching debugger #8

Open theoribeiro opened 5 years ago

theoribeiro commented 5 years ago

Hey @alhazmy13 ,

Have you found a way to attach a python debugger to serverless-offline-python by any chance? I wish I could set up breakpoints and debug my functions step by step since they are getting quite big. I am strongly considering moving to Node.js just because of this.

Best,

Theo

jcouser commented 5 years ago

Hi @theobribeiro,

Just curious if you ever found a solution for breakpointing python?

theoribeiro commented 5 years ago

Hey @jcouser,

Yeah, I did. I am using Pycharm, which in turn uses the pydev debugger to debug. I created a remote debug configuration in Pycharm: image

And copied that line mentioned above to the top of Serverless' Python invoke script:

./node_modules/serverless/lib/plugins/aws/invokeLocal/invoke.py

import pydevd pydevd.settrace('localhost', port=50059, stdoutToServer=True, stderrToServer=True, suspend=False)

Now all you need to do is run your remote debugging server and every time a Python function is invoked locally it will connect to it, so your breakpoints will work.

To avoid the unnecessary lag when I don't want it or the error when I'm not running the debugger I am checking for the environment variable DEBUG. Whenever it is set, I want it to connect to my remote debugger.

This is not an ideal solution but works for me. Setting up the VSCode remote debugger should be very similar but with a different debugging library.

Hope this helps

AntoniusGolly commented 5 years ago

Thanks for the walk through, @theoribeiro. I have the problem that the invoke.py script is not executed. I guess it is used when you use invoke but I use serverless offline start. Any suggestions where to put the two lines when using offline?

roshanpiu commented 4 years ago

@AntoniusGolly for serverless offline you need to add

import pydevd_pycharm
pydevd_pycharm.settrace('localhost', port=50059, stdoutToServer=True, stderrToServer=True)

to

./node_modules/serverless-offline/dist/lambda/handler-runner/python-runner/invoke.py

leoplana commented 2 years ago

If one ever need to attach VS Code debugger this was the way I did it

pip install ptvsd==4.3.2

prepare-debug.js

const fs = require('fs');
const debugSnippet = `
# Added automatically by prepare-debug.js on ${new Date()}
import os
import ptvsd
if os.environ.get('DEBUG','false').lower() == 'true':
    ptvsd.enable_attach(address=('0.0.0.0', 5890))
    print("Waiting for debugger attach on port 5890...")
    ptvsd.wait_for_attach()
    print("Debugger attached!")
`
const fileName = './node_modules/serverless-offline/dist/lambda/handler-runner/python-runner/invoke.py';
const data = fs.readFileSync(fileName)
const fileContent = data.toString('utf-8', 0, data.length);

if(fileContent.includes('prepare-debug.js')) {
    console.log('Debugger snippet had already been added!');
    process.exit(0)
}

const fd = fs.openSync(fileName, 'w+')
const insert = Buffer.from(debugSnippet)
fs.writeSync(fd, insert, 0, insert.length, 0)
fs.writeSync(fd, data, 0, data.length, insert.length)
fs.close(fd, (err) => {
  if (err) throw err;
});
console.log('Debugger snippet has been successfully added!');

package.json

...
 "scripts": {
    "predebug": "node prepare-debug.js",
    "debug": "DEBUG=true sls offline start --host 0.0.0.0"
    }
 ...

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
           "name": "Serverless Debug",
           "type": "python",
           "request": "attach",
           "port": 5890,
           "host": "localhost",
           "console": "integratedTerminal",
           "pathMappings": [
               {
                   "localRoot": "${workspaceFolder}",
                   "remoteRoot": "."
               }
           ]
       }
   ]
}