Debug python flask application in vim - python

Does anybody debug flask application in vim using this one for example.
What I want:
I want to set break point in controller method for example
def login():
(breakpoint)>> some code
...
...
Somehow run flask app and when I send for example login form stop on this breakpoint and debug source code.
Thanks.

Do you know about Python debbuger? You can set breakpoints anywhere in your code using this line:
import pdb; pdb.set_trace()
If you're using vim, you might like this shortcut as well:
:ia pdb import pdb; pdb.set_trace()<ESC>

Below is the relevant parts of my setup that allows me to press F7 on a line and get a pdb.set_trace() line inserted. Shift+F7 removes it again. The debugging itself happens outside of vim (on the command-line where the program is executed), but has never let me down.
This implementation requires the brilliant ipdb, but should be easy enough to modify if/as necessary.
~/.vim/ftplugin/python/python.vim:
...
map <S-F7> :py RemoveBreakpoints()<CR>
map <F7> :py SetBreakpoint()<CR>
...
~/.vim/ftplugin/python/custom.py:
...
def SetBreakpoint():
nLine = int( vim.eval('line(".")') )
strLine = vim.current.line
strWhite = re.search('^(\s*)', strLine).group(1)
vim.current.buffer.append(
(
"%(space)spdb.set_trace() %(mark)s Breakpoint %(mark)s" %
{'space': strWhite, 'mark': '#' * 30}
),
nLine - 1
)
for strLine in vim.current.buffer:
if strLine == "import ipdb as pdb":
break
else:
vim.current.buffer.append('import ipdb as pdb', 2)
vim.command('normal j1')
vim.command('write')
def RemoveBreakpoints():
nCurrentLine = int( vim.eval('line(".")') )
nLines = []
nLine = 1
for strLine in vim.current.buffer:
if strLine == 'import ipdb as pdb' or strLine.lstrip().startswith('pdb.set_trace()'):
nLines.append(nLine)
nLine += 1
nLines.reverse()
for nLine in nLines:
vim.command('normal %dG' % nLine)
vim.command('normal dd')
if nLine < nCurrentLine:
nCurrentLine -= 1
vim.command('normal %dG' % nCurrentLine)
vim.command('write')
...

Related

Call python function with arguments and get returned value in autohotkey

I have a python script called "server.py" and inside it I have a function def calcFunction(arg1): ... return output How can I call the function calcFunction with arguments and use the return value in autohotkey? This is what I want to do in autohotkey:
ToSend = someString ; a string
output = Run server.py, calcFunction(ToSend) ; get the returned value from the function with ToSend as argument
Send, output ; use the returned value in autohotkey
I have looked online but nothing seems to fully answer my question. Can it even be done?
In order to send your parameters to Python, you could use arguments from within your Python script. You can do this with the sys library:
import sys
print(sys.argv[0]) # name of file
print(sys.argv[1]) # first argument
print(sys.argv[2]) # second argument...
From within your AutoHotKey script, you can send parameters to the Python script by adding them as arguments right after specifying the file name:
RunWait, server.py "This will be printed as the first argument!" "This is the second!"
Then, to get the output of the function back to AHK, you could use sys again by utilizing it's exit() function:
sys.exit(EXIT_NUMBER)
And back in AHK, you recieve the EXIT_NUMBER inside the variable ErrorLevel.
Put all together, your code should look something like this:
; AHK
RunWait, server.py "%ToSend%"
# Python
sys.exit(calcFunction(sys.argv[1]))
; AHK
MsgBox %ErrorLevel%
using python COM server, ahk can really calls python functions. directly.
you use it like this: MsgBox % pythonComServer.toUppercase("hello world")
simple example: return uppercased string
use the python part from How to program hotstrings in python like in autohotkey and use this for ahk part:
call python function uppercase.ahk
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
SetBatchLines, -1
#KeyHistory 0
ListLines Off
pythonComServer:=ComObjCreate("Python.stringUppercaser")
;or
; pythonComServer:=ComObjCreate("{C70F3BF7-2947-4F87-B31E-9F5B8B13D24F}") ;use your own CLSID
MsgBox % pythonComServer.toUppercase("hello world")
Exitapp
f3::Exitapp
customized version: (math) use SymPy to simplify Expression
read this first to understand: How to program hotstrings in python like in autohotkey
sympy com server.py
from sympy import simplify, Number, N
from sympy.parsing.sympy_parser import standard_transformations, implicit_multiplication_application, convert_xor
from sympy.parsing.sympy_parser import parse_expr
from decimal import Decimal
from winsound import MessageBeep
transformations = standard_transformations + (implicit_multiplication_application, convert_xor)
def removeTrailingZerosFromNum(num):
dec = Decimal(str(num))
tup = dec.as_tuple()
delta = len(tup.digits) + tup.exponent
digits = ''.join(str(d) for d in tup.digits)
if delta <= 0:
zeros = abs(tup.exponent) - len(tup.digits)
val = '0.' + ('0' * zeros) + digits
else:
val = digits[:delta] + ('0' * tup.exponent) + '.' + digits[delta:]
val = val.rstrip('0')
if val[-1] == '.':
val = val[:-1]
if tup.sign:
return '-' + val
return val
def removeTrailingZerosFromExpr(operatorObject):
if operatorObject.args:
return type(operatorObject)(*[removeTrailingZerosFromExpr(i) for i in operatorObject.args])
else:
try:
return Number(removeTrailingZerosFromNum(operatorObject))
except:
return operatorObject
def removeTrailingZerosFromExprOrNumber(operatorObject):
try:
return removeTrailingZerosFromNum(operatorObject)
except:
return removeTrailingZerosFromExpr(operatorObject)
class BasicServer:
# list of all method names exposed to COM
_public_methods_ = ["parExprN"]
#staticmethod
def parExprN(clipBak):
parsed = parse_expr(clipBak, transformations=transformations)
simplified = simplify(N(parsed))
finalStr = str(removeTrailingZerosFromExprOrNumber(simplified))
MessageBeep(-1)
return finalStr.replace("**", "^")
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print("Error: need to supply arg (""--register"" or ""--unregister"")")
sys.exit(1)
else:
import win32com.server.register
import win32com.server.exception
# this server's CLSID
# NEVER copy the following ID
# Use "print(pythoncom.CreateGuid())" to make a new one.
myClsid="{4530C817-6C66-46C8-8FB0-E606970A8DF6}"
# this server's (user-friendly) program ID, can be anything you want
myProgID="Python.SimplifyExpr"
import ctypes
def make_sure_is_admin():
try:
if ctypes.windll.shell32.IsUserAnAdmin():
return
except:
pass
exit("YOU MUST RUN THIS AS ADMIN")
if sys.argv[1] == "--register":
make_sure_is_admin()
import pythoncom
import os.path
realPath = os.path.realpath(__file__)
dirName = os.path.dirname(realPath)
nameOfThisFile = os.path.basename(realPath)
nameNoExt = os.path.splitext(nameOfThisFile)[0]
# stuff will be written here
# HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\${myClsid}
# HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{c2467d33-71c5-4057-977c-e847c2286882}
# and here
# HKEY_LOCAL_MACHINE\SOFTWARE\Classes\${myProgID}
# HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.SimplifyExpr
win32com.server.register.RegisterServer(
clsid=myClsid,
# I guess this is {fileNameNoExt}.{className}
pythonInstString=nameNoExt + ".BasicServer", #sympy com server.BasicServer
progID=myProgID,
# optional description
desc="(math) SymPy simplify Expression",
#we only want the registry key LocalServer32
#we DO NOT WANT InProcServer32: pythoncom39.dll, NO NO NO
clsctx=pythoncom.CLSCTX_LOCAL_SERVER,
#this is needed if this file isn't in PYTHONPATH: it tells regedit which directory this file is located
#this will write HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{4530C817-6C66-46C8-8FB0-E606970A8DF6}\PythonCOMPath : dirName
addnPath=dirName,
)
print("Registered COM server.")
# don't use UseCommandLine(), as it will write InProcServer32: pythoncom39.dll
# win32com.server.register.UseCommandLine(BasicServer)
elif sys.argv[1] == "--unregister":
make_sure_is_admin()
print("Starting to unregister...")
win32com.server.register.UnregisterServer(myClsid, myProgID)
print("Unregistered COM server.")
else:
print("Error: arg not recognized")
to register:
python "sympy com server.py" --register
sympy com client.ahk
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
SetBatchLines, -1
#KeyHistory 0
ListLines Off
sympyComServer:=ComObjCreate("Python.SimplifyExpr")
;or
; pythonComServer:=ComObjCreate("{4530C817-6C66-46C8-8FB0-E606970A8DF6}") ;use your own CLSID
; clipboard:=sympyComServer.parExprN("1+3*7")
clipboard:=sympyComServer.parExprN("1/3 + 1/2")
$#s::
clipboard:=sympyComServer.parExprN(clipboard)
return
f3::Exitapp

How to put text in input line: how to ask for user input on the command line while providing a 'default' answer that the user can edit or delete?

I am creating a Python script that asks for input from the command line. The user will have the ability to edit a part of a file. I can ask for the new information and overwrite it in the file, no problem. But I would rather have the to-edit part of the file already put in the command line, so it does not have to be typed completely over. Is this possible?
File:
1|This file
2|is not empty
Example:
>>>edit line 2
Fetching line 2
Edit the line then hit enter
>>>is not empty #This is written here by the script, not by the user
Which then can be changed to
>>>is not full either
Edited file
Afther which the file has changed to:
1|This file
2|is not full either
I hope it's clear what I am trying to accomplish.
This question has been said to answer my question, it does to a certain extent. It does when I am running Linux with readline. However, I am not. I am using Windows and am not using readline. I would like to only use the standard library.
An answer for Windows is also provided with that question. However, I get an ImportError with win32console, it might be because mentioned question is not about Python3.4, but mine is.
Also, I was wondering if this was possible with the standard library, not with an external library.
Unfortunately, I don't know if kind of input() with default value is available in standard library.
There is an external solution - use win32console as mentioned in this answer. However, it has two pitfalls as far as I can see. First, the import is bundled in a package pywin32. So you would use pip install pywin32, except it does not work, because of the second pitfall: the information about the package at pypi is outdated, it says that package is incompatible with Python 3.4...
But in fact, it can work! You should follow the "Download URL" visible at pypi project page (i.e. https://sourceforge.net/projects/pywin32/files/pywin32/ ) and install latest build. I just installed build 219 for Py3.4, as I myself also use this Python version. On the page installers are provided for several Python versions for 32bit and 64bit Windows.
Also, I've tweaked the code from above-linked SO answer to work in Python 3:
import win32console
_stdin = win32console.GetStdHandle(win32console.STD_INPUT_HANDLE)
def input_def(prompt, default=''):
keys = []
for c in str(default):
evt = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
evt.Char = c
evt.RepeatCount = 1
evt.KeyDown = True
keys.append(evt)
_stdin.WriteConsoleInput(keys)
return input(prompt)
if __name__ == '__main__':
name = input_def('Folder name: ', 'it works!!!')
print()
print(name)
This works on my Windows machine... If this does not work on yours, can you provide the error message?
I have written a line editor which hopefully does what you are looking for. But it is a quick-and-dirty hack. It is Windows only and written with CPython 3.6.5 on Windows 10, so its use might be limited. It has been tested on codepage 1252 (ANSI Latin 1; Western European (Windows)) and codepage 65001 (utf-8). It is very basic and a bit sluggish as it is not speed-optimized. (I should rewrite it in C but I do not have the time.) It is hardly tested and poorly documented.
import msvcrt
import os
import sys
if os.name != 'nt':
raise NotImplementedError('This module works only on MS Windows!')
CTRL_00 = 0
CTRL_E0 = 224
KEY_BACKSPACE = 8
KEY_DELETE = 83 # CTRL
KEY_END = 79 # CTRL
KEY_ESC = 27
KEY_HOME = 71 # CTRL
KEY_INSERT = 82 # CTRL
KEY_LEFT = 75 # CTRL
KEY_RETURN = 13
KEY_RIGHT = 77 # CTRL
flush = sys.stdout.flush
write = sys.stdout.write
mode = ('[OVR]> ', '[INS]> ') # overwrite, insert
prefix = len(mode[0])
def _update_line(insert, source, length, line, target):
"""Write a new line and position the cursor.
source: previous cursor position
length: old line length
line: edited line
target: next cursor position
"""
write('\b' * source) # set cursor to start of line
write(' ' * length) # erase old line
write('\b' * length) # again, set cursor to start of line
write(mode[insert] + line[prefix:]) # write updated line
write('\b' * (len(line) - target)) # set cursor to new position
flush() # write buffer to screen
def mswin_line_edit(default_string, insert=True):
"""Edit a MS Windows CLI line."""
insert = insert
line = mode[insert] + default_string
count = len(line)
before = line[:count]
after = line[count:]
print(line, end='', flush=True)
cursor = count
while True:
key = msvcrt.getwch()
num = ord(key)
if num == KEY_ESC: # abort edit
return default_string
if num == KEY_RETURN: # finish edit
return line
if num == KEY_BACKSPACE: # delete character before cursor
if cursor > prefix:
before = line[:cursor - 1]
after = line[cursor:]
line = before + after
_update_line(insert, cursor, count, line, cursor - 1)
cursor -= 1
count = len(line)
elif num == CTRL_E0 or num == CTRL_00: # CTRL
ctrl = ord(msvcrt.getwch())
if ctrl == KEY_END: # set cursor after last character
if cursor < count:
before = line
after = ''
_update_line(insert, cursor, count, line, count)
cursor = count
elif ctrl == KEY_HOME: # set cursor before first character
if cursor > prefix:
before = ''
after = line
_update_line(insert, cursor, count, line, prefix)
cursor = prefix
elif ctrl == KEY_LEFT: # move cursor 1 character to the left
if cursor > prefix:
before = line[:cursor]
after = line[cursor:]
_update_line(insert, cursor, count, line, cursor - 1)
cursor -= 1
elif ctrl == KEY_RIGHT: # move cursor 1 character to the right
if cursor < count:
before = line[:cursor]
after = line[cursor:]
_update_line(insert, cursor, count, line, cursor + 1)
cursor += 1
elif ctrl == KEY_DELETE: # delete character after cursor
if cursor < count:
before = line[:cursor]
after = line[cursor + 1:]
line = before + after
_update_line(insert, cursor, count, line, cursor)
count = len(line)
elif ctrl == KEY_INSERT: # switch insert/overwrite mode
insert ^= True
_update_line(insert, cursor, count, line, cursor)
else: # ordinary character
before = line[:cursor] + key
if insert:
after = line[cursor:]
else:
after = line[cursor + 1:]
line = before + after
_update_line(insert, cursor, count, line, cursor + 1)
cursor += 1
count = len(line)
if __name__ == '__main__':
test_string = input('test string: ')
result = mswin_line_edit(test_string)
print(f'\n{result}')
You could do it with tkinter:
from tkinter import *
def enter():
global commandEntry
command = commandEntry.get()
# Do stuff with command
commandEntry.delete(0, END)
def edit_line(line):
global commandEntry
commandEntry.insert(0, line)
root = Tk()
messageVar = StringVar()
messageVar.set("Enter a command:")
message = Label(root, textvariable=messageVar)
commandEntry = Entry(root)
enterButton = Button(root, text="Enter", command=enter)
root.mainloop()
You should just have 2 variables: one for standard string, one for string that will user change by itself.
Like:
str1 = 'String that is standard'
str2 = str1 #it usually will be standard string
usr = input('your text goes here')
if len(usr) != 0:
str2 = usr
#and here goes code for writing string into file

Python refresh file from disk

I have a python script that calls a system program and reads the output from a file out.txt, acts on that output, and loops. However, it doesn't work, and a close investigation showed that the python script just opens out.txt once and then keeps on reading from that old copy. How can I make the python script reread the file on each iteration? I saw a similar question here on SO but it was about a python script running alongside a program, not calling it, and the solution doesn't work. I tried closing the file before looping back but it didn't do anything.
EDIT:
I already tried closing and opening, it didn't work. Here's the code:
import subprocess, os, sys
filename = sys.argv[1]
file = open(filename,'r')
foo = open('foo','w')
foo.write(file.read().rstrip())
foo = open('foo','a')
crap = open(os.devnull,'wb')
numSolutions = 0
while True:
subprocess.call(["minisat", "foo", "out"], stdout=crap,stderr=crap)
out = open('out','r')
if out.readline().rstrip() == "SAT":
numSolutions += 1
clause = out.readline().rstrip()
clause = clause.split(" ")
print clause
clause = map(int,clause)
clause = map(lambda x: -x,clause)
output = ' '.join(map(lambda x: str(x),clause))
print output
foo.write('\n'+output)
out.close()
else:
break
print "There are ", numSolutions, " solutions."
You need to flush foo so that the external program can see its latest changes. When you write to a file, the data is buffered in the local process and sent to the system in larger blocks. This is done because updating the system file is relatively expensive. In your case, you need to force a flush of the data so that minisat can see it.
foo.write('\n'+output)
foo.flush()
I rewrote it to hopefully be a bit easier to understand:
import os
from shutil import copyfile
import subprocess
import sys
TEMP_CNF = "tmp.in"
TEMP_SOL = "tmp.out"
NULL = open(os.devnull, "wb")
def all_solutions(cnf_fname):
"""
Given a file containing a set of constraints,
generate all possible solutions.
"""
# make a copy of original input file
copyfile(cnf_fname, TEMP_CNF)
while True:
# run minisat to solve the constraint problem
subprocess.call(["minisat", TEMP_CNF, TEMP_SOL], stdout=NULL,stderr=NULL)
# look at the result
with open(TEMP_SOL) as result:
line = next(result)
if line.startswith("SAT"):
# Success - return solution
line = next(result)
solution = [int(i) for i in line.split()]
yield solution
else:
# Failure - no more solutions possible
break
# disqualify found solution
with open(TEMP_CNF, "a") as constraints:
new_constraint = " ".join(str(-i) for i in sol)
constraints.write("\n")
constraints.write(new_constraint)
def main(cnf_fname):
"""
Given a file containing a set of constraints,
count the possible solutions.
"""
count = sum(1 for i in all_solutions(cnf_fname))
print("There are {} solutions.".format(count))
if __name__=="__main__":
if len(sys.argv) == 2:
main(sys.argv[1])
else:
print("Usage: {} cnf.in".format(sys.argv[0]))
You take your file_var and end the loop with file_var.close().
for ... :
ga_file = open(out.txt, 'r')
... do stuff
ga_file.close()
Demo of an implementation below (as simple as possible, this is all of the Jython code needed)...
__author__ = ''
import time
var = 'false'
while var == 'false':
out = open('out.txt', 'r')
content = out.read()
time.sleep(3)
print content
out.close()
generates this output:
2015-01-09, 'stuff added'
2015-01-09, 'stuff added' # <-- this is when i just saved my update
2015-01-10, 'stuff added again :)' # <-- my new output from file reads
I strongly recommend reading the error messages. They hold quite a lot of information.
I think the full file name should be written for debug purposes.

Ipython customize prompt to display cell run time

i am wondering how to configure Ipython so that it adds the run time of the last command in milliseconds/seconds to the right command prompt. This could be done in ZSH/Bash shells as illustrated here https://coderwall.com/p/kmchbw
How should I go about doing this?
This is a code snippet that times each statement and prints it right adjusted before the next prompt, and also makes the value accessible by name 'texc'.
# Assumes from __future__ import print_function
from time import time
import blessings # Not a necessary requirement
class ExecTimer(object):
def __init__(self, ip):
self.shell = ip
self.t_pre = time()
self.texc = 0
self.prev_texc = 0
self.term = blessings.Terminal()
def pre_execute(self):
self.t_pre = time()
def post_execute(self):
self.prev_texc = self.texc
self.texc = round(time() - self.t_pre, 4)
print(self.term.bold_blue(
'{} s'.format(self.texc).rjust(self.term.width - 1)
))
# Only add or update user namespace var if it is safe to do so
if 'texc' not in self.shell.user_ns or \
self.shell.user_ns['texc'] == self.prev_texc:
self.shell.push({'texc': self.texc})
else:
pass
def register(self):
self.shell.events.register('pre_execute', self.pre_execute)
self.shell.events.register('post_execute', self.post_execute)
ExecTimer(get_ipython()).register()
To print it above the in-prompt instead, remove the print, and in ipython_config.py set:
c.PromptManager.in_template = '{texc} s\nIn[\\#]: '
or in the same file (startup.py) use
get_ipython().run_line_magic(
'config',
r"PromptManager.in_template = '{texc} s\nIn[\\#]: '"
)
For those who are interested, please refer to this issue opened in Github.
https://github.com/ipython/ipython/issues/5237

python configparser hangs silently

I have a feeling I'm being stupid. Given this ini file:
[main]
source1 = ./testing/sdir1
sync1 = ./testing/sydir1
archive1 = ./testing/adir1
source2 = ./testing/sdir2
sync2 = ./testing/sydir2
archive2 = ./testing/adir2
[logging]
log_dir = .
log_file = pixelsync.log
log_level = DEBUG
The following code hangs:
import ConfigParser
CONFIG_FILE = 'pixelsync.ini'
def parse_config() :
"""read details from the config file"""
global CONFIG_FILE
config = ConfigParser.SafeConfigParser()
config.read(CONFIG_FILE)
index = 1
while True :
if config.has_option('main', 'source' + str(index)) and \
config.has_option('main', 'sync' + str(index)) and \
config.has_option('main', 'archive' + str(index)) :
result = ( config.get('main', 'source' + str(index)),
config.get('main', 'sync' + str(index)),
config.get('main', 'archive' + str(index)))
index += 1
else :
if index == 1 :
print "could not setup any trios from the config file. exiting."
sys.exit(1)
return result
if __name__ == '__main__' :
options = parse_config()
It hangs on the 'if' clause.
If I replace the 'if' clause with :
if config.has_option('main', 'source1' ) and \
config.has_option('main', 'sync1' ) and \
config.has_option('main', 'archive1' ) :
it doesn't hang. (doesn't do what I want since I need to loop through an arbitrary number of sets of three, but it doesn't silently hang.
Python v2.7.3 on ubuntu 12.04 (Precise), 32bit.
The reason your program hangs is it never breaks out of the loop - it goes on forever. Rather than simply setting result, you need to return it. (An alternative is to set it and then use break to break out of the loop and return, but that is somewhat roundabout. It's better to simply return it straight away.
Note that doing while True: and counting like that isn't very Pythonic, the preferred approach is to instead use itertools.count().
E.g:
import itertools
...
for index in itertools.count(1):
...
Note that this shows a design flaw. You probably want to have a way of knowing if you are never going to get a suitable result. Infinite loops are generally bad.

Categories

Resources