Use of set_timeout with Sublime Text 3 API - python

I am trying to use (as the title says) the
set_timeout
function of sublime text 3 in a plugin.
For what I understood, the use of a lambda function is required in many cases. So I tried this simple test :
class SetTimeoutTestCommand(sublime_plugin.WindowCommand):
def run(self):
for x in range(1,10):
sublime.set_timeout(lambda : print(x), 4000)
So I expected that I will have number printed one at a time with a delay of 4 seconds between each. As explained in the Sublime 3 API :
Runs the callback in the main thread after the given delay (in milliseconds). Callbacks with an equal delay will be run in the order they were added.
But instead I have 9 '9' that are printed after 4 seconds. So all '9' are printed at the same time, based on the first iteration of the loop.
Do you have an idea of what I can do to solve this ?
Thanks in advance !
Edit : I found this which work (well, which print '9' 9 times with 1 second delay between each :
class SetTimeoutTestCommand(sublime_plugin.WindowCommand):
def run(self):
for x in range(1,10):
sublime.set_timeout(lambda : print(x), x*1000)
But on problem remains : it only prints out '9' ....

To print different numbers change your plugin script on this
class SetTimeoutTestCommand(sublime_plugin.WindowCommand):
def run(self, edit):
for x in range(1,10):
sublime.set_timeout(lambda x=x: print(x), x*1000)
Because all lambda functions refer to the same x and when it's executed the x value reaches 9.

The first thing to understand is that the set_timeout calls return immediately. That is, you are scheduling all of the print functions to be run in 1 second. Not 1 second from each other. Based on your edit, it seems you figured that out, but just thought I would clarify.
As for always printing 9, all of the print statements are referencing the same value. So, even when the first print is scheduled, it references the same x value that you are incrementing. By the time the print actually runs (1 second later), the value of x is 9. Thus, 9 is printed for every scheduled callback.
Hope that clarifies things some.

Related

Can I return 2 times in a def function?

I have a problem with my code.I'm working with API now, and when I call it, it will show me some result. And I want to show a loading text like this : "300: Calculating" to know that my code is processing , untill the result show out , the "300: Calculating " text will disappear. And my code is in a def function.
My codeis roughly as below :
#api_view(['POST'])
def Measurementwarning_response():
i = 0
while i < 3:
if i == 1:
message_code = "300: Calculating"
predict_response1 = {
"message_code": message_code,
}
predict_response = predict_response1
return HttpResponse(json.dumps(predict_response))
if i == 2:
message_code = "200. Sucessfully : Hello world"
predict_response2 = {
'message_code': message_code,
}
predict_response = predict_response2
time.sleep(2)
return HttpResponse(json.dumps(predict_response))
i = i +1
I hope that after I call this API (Measurementwarning_response). The loading text "300: Calculating" will show out like this :
This loading text "300: Calculating" will exisit whithin 2 seconds
End then, after 2 seconds, the result "200. Sucessfully : Hello world" will show out. And "300: Calculating" text will disappear like this This is the result will show out after 2 seconds and the "300: Calculating" text will disappear
I have been tried to make a while loop and return HttpResponse(json.dumps(predict_response)) 2 times. But it seems to be that I can not return 2 times in a function.I have been tried many times but I still can not do it. I hope you guys will take a look and comment in below to let me know what should I do with my code. Thank you guys so much
return statement ends the function. so you cannot return twice. You can use yield and generator function in python as an alternative.
The yield statement suspends a function’s execution and sends a value back to the caller, but retains enough state to enable the function to resume where it left off. When the function resumes, it continues execution immediately after the last yield run. This allows its code to produce a series of values over time, rather than computing them at once and sending them back like a list.
def simpleGeneratorFun():
yield 1
yield 2
yield 3
# Driver code to check above generator function
for value in simpleGeneratorFun():
print(value)
Output:
1
2
3

Why doesn't it keep incrementing every time I run the block?

I'm an absolute beginner, and I don't understand why a is not incremented every time I run the code. It always prints a = 0 and a = 1.
a = 0
b = 2
print ("a = {}".format(a))
a = a + 1
print ("a = {}".format(a))
Output
I'm working on Google Colab. Thanks in advance!
EDIT: I just noticed if I keep the two first lines on a separate block like this, the code does increment. Why??
Use two separate cells, one for declaring the variables and one for incrementing:

How do I run a conditional statement "only once" and every time it changes?

I might be asking a simple question. I have a python program that runs every minute. But I would like a block of code to only run once the condition changes? My code looks like this:
# def shortIndicator():
a = int(indicate_5min.value5)
b = int(indicate_10min.value10)
c = int(indicate_15min.value15)
if a + b + c == 3:
print("Trade posible!")
else:
print("Trade NOT posible!")
# This lets the processor work more than it should.
"""run_once = 0 # This lets the processor work more than it should.
while 1:
if run_once == 0:
shortIndicator()
run_once = 1"""
I've run it without using a function. But then I get an output every minute. I've tried to run it as a function, when I enable the commented code it sort of runs, but also the processing usage is more. If there perhaps a smarter way of doing this?
It's really not clear what you mean, but if you only want to print a notification when the result changes, add another variable to rembember the previous result.
def shortIndicator():
return indicate_5min.value5 and indicate_10min.value10 and indicate_15min.value15
previous = None
while True:
indicator = shortIndicator()
if previous is None or indicator != previous:
if indicator:
print("Trade possible!")
else:
print("Trade NOT possible!")
previous = indicator
# take a break so as not to query too often
time.sleep(60)
Initializing provious to None creates a third state which is only true the first time the while loop executes; by definition, the result cannot be identical to the previous result because there isn't really a previous result the first time.
Perhaps also notice the boolean shorthand inside the function, which is simpler and more idiomatic than converting each value to an int and checking their sum.
I'm guessing the time.sleep is what you were looking for to reduce the load of running this code repeatedly, though that part of the question remains really unclear.
Finally, check the spelling of possible.
If I understand it correctly, you can save previous output to a file, then read it at the beginning of program and print output only if previous output was different.

Conditionally increase integer count with an if statement in python

I'm trying to increase the count of an integer given that an if statement returns true. However, when this program is ran it always prints 0.I want n to increase to 1 the first time the program is ran. To 2 the second time and so on.
I know functions, classes and modules you can use the global command, to go outside it, but this doesn't work with an if statement.
n = 0
print(n)
if True:
n += 1
Based on the comments of the previous answer, do you want something like this:
n = 0
while True:
if True: #Replace True with any other condition you like.
print(n)
n+=1
EDIT:
Based on the comments by OP on this answer, what he wants is for the data to persist or in more precise words the variable n to persist (Or keep it's new modified value) between multiple runs times.
So the code for that goes as(Assuming Python3.x):
try:
file = open('count.txt','r')
n = int(file.read())
file.close()
except IOError:
file = open('count.txt','w')
file.write('1')
file.close()
n = 1
print(n)
n += 1
with open('count.txt','w') as file:
file.write(str(n))
print("Now the variable n persists and is incremented every time.")
#Do what you want to do further, the value of n will increase every time you run the program
NOTE:
There are many methods of object serialization and the above example is one of the simplest, you can use dedicated object serialization modules like pickle and many others.
If you want it to work with if statement only. I think you need to put in a function and make to call itself which we would call it recursion.
def increment():
n=0
if True:
n+=1
print(n)
increment()
increment()
Note: in this solution, it would run infinitely.
Also you can use while loop or for loop as well.
When you rerun a program, all data stored in memory is reset. You need to save the variable somewhere outside of the program, on disk.
for an example see How to increment variable every time script is run in Python?
ps. Nowadays you can simply do += with a bool:
a = 1
b = True
a += b # a will be 2

Python: printing bottom up

I have a code in python and I need to print 3 results, the first one at the bottom, the third on the top.
The terminal will print in this order:
first
(pause)
second
(pause)
third
I would like to print in this order instead (there will be a pause in between the output):
...third
...second (pause)
first to be printed (then pause)
in order to simulate this I'm using this sequence of print statement:
from time import sleep
print '1'
sleep(1)
print '2'
print '1'
sleep(1)
print '3'
print '2'
print '1'
This bottom up printing should be only used specifically for this 3 line output and not globally for all the output.
Is that possible? Thank you
UPDATE:
It seems that the only library I can effectively use for modifying the newline order of the terminal is curses.
I will give it a try. Thank you.
I think you want to "overwrite" the print outputs for every successive run. If newlines are not a hard constraint, you can do something like this:
import sys
import time
for i in range(3):
sys.stdout.write('\r' + ','.join([str(a) for a in range(i+1, 0, -1)]))
sys.stdout.flush()
time.sleep(1)
sys.stdout.write('\n')
This will first print 1, wait for a second, overwrite the 1 with 2,1, wait for a second and then overwrite the 2,1 with 3,2,1, wait for a second and exit.
The interesting portion is the use of the \r in the output string - this is the Unix carriage return which causes the stdout file pointer in terminals to move to the leftmost position. Now that the pointer is located at the left-most position, we then print the next set of characters in effect overwriting the previous output.
I use sys.stdout.write to avoid the implicit newline or space that print adds. The range is written in this way to generate a reversed list of numbers to print. The flush is needed to force the characters to be flushed to the output.
This only works as long as the output is on a single line - multi-line outputs like in your example will not work with this method. If you must have multi-line outputs, the curses library is your best bet.
Examples :
results = ["1","2","3"]
print "\n".join(results)
1
2
3
print "\n".join(results[::-1])
3
2
1
Yes it is possible. Please post any code that you are stuck with so that people can help you faster. You can use reversed(), a python built-in to reverse any iterable you are trying to print.
For example:
list = ['1', '2', '3']
for item in list:
print item
# You get
# 1
# 2
# 3
Now if you just want to reverse this order of printing you can do something like this:
for item in reversed(list):
print item
# You get
# 3
# 2
# 1
Hope this helps.

Categories