Controlling input/output of Python interactive shell - python

I have to evaluate (millions of) Python expressions e.g. (int(a) >> 8 == 4) and b
in my OCaml program. There is pycaml but I failed to get it working.
So I turned to another idea: control the input/output of Python interpreter directly.
Ideally I would like to intercept both the input/output of the interpreter itself.
By sending a = 3 b = 5 a > b to the interpreter, I would then be able to get the result False, as if I have done this by keyboard..
>>> a = 3
>>> b = 5
>>> a > b
False
>>>
However, my code doesn't working as expected (while the same code worked for some interactive program)
let (readme, writeme) = Unix.open_process "python -u";;
let _ = output_string writeme "3 + 5\n" in
let _ = flush writeme in
let result = input_line readme in
print_endline result;;
I tried changing 3 + 5\n to print 3\n, but it still hangs at input_line.
Is there any better way to do this? I would need to evaluate quite a lot of
expressions, so I don't really want to do this via a temp file. Any help appreciated,
Thanks.

I'm not going to comment on the weirdness of the entire concept (driving python to evaluate expressions from o'caml) but it seems like you might want to look into writing a python program that is an eval cycle that reads/writes a string from/to a pipe. Look up the eval command.

You can supply a command to the interpreter through the command line:
$ python -c 'a = 3; b = 5; print a > b'
False
Is that adequate for your needs?
If you're concerned about opening the interpreter repeatedly, you could generate and evaluate many expressions at once. I'm not sure what the upper limit is, but I was able to evaluate and print 200 concatenated copies of a = 3; b = 5; print a > b; without any problem.

Related

How to catch the terminal output?

I'm working on https://github.com/JsBergbau/MiTemperature2 with raspberry pi 3 model b. It's working properly on its own infinite loop but I am not able to catch the output from the terminal. How can I reach to output by using python?
Here is the part of printing:
measurement_time = datetime.datetime.fromtimestamp(measurement.timestamp)
print(measurement_time)
humidity=int.from_bytes(data[2:3],byteorder='little')
print("Temperature: " + str(temp))
print("Humidity: " + str(humidity))
voltage=int.from_bytes(data[3:5],byteorder='little') / 1000.
print("Battery voltage:",voltage,"V")
measurement.temperature = temp
measurement.humidity = humidity
measurement.voltage = voltage
measurement.sensorname = args.name
batteryLevel = min(int(round((voltage - 2.1),2) * 100), 100) #3.1 or above --> 100% 2.1 --> 0 %
measurement.battery = batteryLevel
print("Battery level:",batteryLevel)
measurement_time = datetime.datetime.fromtimestamp(measurement.timestamp)
Here is the script I run on terminal:
python3 LYWSD03MMC.py -d AA:BB:CC:DD:EE:FF
And here is the output:
2021-08-05 11:21:24
Temperature: 24.79
Humidity: 47
Battery voltage: 3.092 V
Battery level: 99
here is the run command and sample output, thanks for helps, best regards.
Change your code so it returns the information instead of just printing it. If you have code which looks like
something = some_function_call(123)
print(something)
other_one = different_function("some data here?").strip()
print(other_one)
probably refactor to
def get_something(number):
return some_function_call(number)
def get_other_one():
return different_function("some data here?").strip()
if __name__ == '__main__':
print(get_something(123))
print(get_other_one())
Now, you can create additional code which retrieves these values without printing them, and does whatever it wants with them. Put them on a web site? Upload them to a database? Rot13 encrypt them and send an email to Bill Gates? Your imagination is the limit.
How exactly you design your code is a broad topic where many books have been written, and more will be. A common arrangement is to make sure the useful parts are in modular functions which do one thing only (ideally without any side effects) so you can import this code and use it from other programs. (That's why the if __name__ part is useful. It makes sure code inside the block doesn't run when you import this file.)
Have you had a closer look at the code? There is a callback option. This is the easiest way to get values from this script. Or is this question more academically on how to capture python output?
If not, that should help you:
Documentation where callback is described:
https://github.com/JsBergbau/MiTemperature2#callback-for-processing-the-data
Accessing the single values:
In sendToInflux.sh https://github.com/JsBergbau/MiTemperature2/blob/master/sendToInflux.sh is an example in which argument are the values like temperature and so on.
Or when using sendToFile.sh it gives line by line
sensorname,temperature,humidity,voltage,humidityCalibrated,timestamp MySensor 20.61 54 2.944 49 1582120122
That data should be easy to process by python or awk.
add commandline
2>&1 | tee result.txt
it can save command line output
If you are running a command from python you can use subprocess.check_output to get the returning output from the terminal. Don't work if the called script runs forever.
Like this:
output = subprocess.check_output([sys.executable, 'LYWSD03MMC.py', '-d', 'AA:BB:CC:DD:EE:FF']).decode()

I want to run small Julia code/modules in python. How should I do that?

I have created a jl file having the following content:
for i in 1:10
println(i)
end
1+2
When I am calling that jl file in python using the following code:
import julia
from julia.api import Julia
j = julia.Julia(compiled_modules=False)
x = j.include("experiment.jl")
only x is being printed as 3. No integers(i) from 1-10 are not being printed.
I am getting following warning:
/opt/conda/lib/python3.7/site-packages/julia/core.py:689: FutureWarning: Accessing `Julia().<name>` to obtain Julia objects is deprecated. Use `from julia import Main; Main.<name>` or `jl = Julia(); jl.eval('<name>')`.
Your julia program is running just fine. As you can see you get the right result from your julia script. And also your loop is running, it is just not printed to the same output stream as the one from python (that is why you don't see it). Here is a discussion how to print to the same output as python's. But I would not bother to much about it, to test if your loop actually runs try something like that:
z = 0
for i in 1:10
z = z + i
end
z + 1

Indentation Problems Pycharm

I'm new to coding and python so i'm doing an online free course. There's one task that i'm supposed to do that is not working properly, and apparently the problem is identation. Here's the code:
c = 0
while c < 5:
c += 1
if c == 3:
continue
print (c)
So the last line is aligned with the previous one, and the code only runs properly after I delete one identation from the last line. How do I configure this to be automatic so I won't have to delete it all the time?
TLDR: In general, no, you cannot configure this automatically. However, there are some specific cases where we can say a statement is definitely in the wrong scope with the help of a linter. The onus is still on the programmer to actually correct the program, though, even with the help of the linter.
General Case:
No programming language can know what scope you'd like a statement to be in. That is for you, the programmer, to express in the language. Python's scoping happens to be determined by whitespace, not curly braces, like in some other popular languages (namely C/C++/Java/Perl).
Consider:
if x:
do_y()
do_z()
vs.
if x:
do_y()
do_z()
Both are legal Python programs, and both are (potentially) logically correct, depending on the application. Maybe you only want to call do_z() if x is true (first example). Or maybe you always want to call do_z() regardless of x (second example). Only the application developer can decide which they want. And which one you want might actually change over time, depending on circumstance. So it should be very clear that this decision (in general) cannot be made automatically.
Using pylint:
However, sometimes what we can say is that some statement is definitely in the wrong scope (like in your example above, a statement immediately after a continue can never be reached).
You can use a linter (like pylint) to help with this:
In test.py I've placed your question code and gave it a quick pylint:
(so) URSA-MattM-MacBook:stackoverflow mmessersmith$ cat test.py
c = 0
while c < 5:
c += 1
if c == 3:
continue
print(c)
(so) URSA-MattM-MacBook:stackoverflow mmessersmith$ pylint test.py
************* Module test
test.py:1:0: C0111: Missing module docstring (missing-docstring)
test.py:1:0: C0103: Constant name "c" doesn't conform to UPPER_CASE naming style (invalid-name)
test.py:6:8: W0101: Unreachable code (unreachable)
------------------------------------------------------------------
Your code has been rated at 5.00/10 (previous run: 5.00/10, +0.00)
Note that this line: test.py:6:8: W0101: Unreachable code (unreachable). That's telling you that line 6 can never be executed, regardless of program state.
Furthermore, note that any linter still cannot automatically correct indent. There are two legal possibilities for where the print(c) statement should be indented:
c = 0
while c < 5:
c += 1
if c == 3:
continue
print (c)
and
c = 0
while c < 5:
c += 1
if c == 3:
continue
print (c)
Both are legal (and reasonable) Python programs! The first will print c in every iteration of the while loop, the second will only print c after the loop has finished. Only you, the programmer, can decide which one you'd like. All the linter can say is "you almost certainly didn't mean to put a statement immediately after a continue, since that code will never be executed".
Again, it is up to you where you'd like the statement. No automated tool can automatically place the statement for you, because it can't possibly know what you want to accomplish.
In your code, print(c) is after continue. But statements after continue is not executed. continue works as ignore the statements after it and go for the next iteration. So print(c) doesn't work. Your code should be like this :-
c = 0
while c < 5:
c += 1
if c == 3:
continue
print (c)
This will print
1
2
4
5

Why does IDLE 3.4 take so long on this program?

EDIT: I'm redoing the question entirely. The issue has nothing to do with time.time()
Here's a program:
import time
start=time.time()
a=9<<(1<<26) # The line that makes it take a while
print(time.time()-start)
This program, when saved as a file and run with IDLE in Python 3.4, takes about 10 seconds, even though 0.0 is printed out from time.time(). The issue is very clearly with IDLE, because when run from the command line this program takes almost no time at all.
Another program that has the same effect, as found by senshin, is:
def f():
a = 9<<(1<<26)
I have confirmed that this same program, when run in Python 2.7 IDLE or from the command line on python 2.7 or 3.4, is near instantaneous.
So what is Python 3.4 IDLE doing that makes it take so long? I understand that calculating this number and saving it to memory is disk intensive, but what I'd like to know is why Python 3.4 IDLE performs this computation and write when Python 2.7 IDLE and command line Python presumably do not.
I would look at that line and pick it apart. You have:
9 << (1 << 26)
(1 << 26) is the first expression evaluated, and it produces a really large number. What this line is saying, is that you are going to multiply the number 1 by 2 to the power of 26, effectively producing the number 2 ** 26 in memory. This is not the problem however. You then shift 9 left by the count of 2 ** 26. This produces a number that is around 50 million digits long in memory (I cant even calculate it exactly!), because the shift left is just too big. Be careful in the future, as shifts by what seems to be small amounts do in fact grow very fast. If it was any larger, your program may have not run at all. Your expression mathematically evaluates to 9 * 2 ** (2 ** 26), if you were curious.
The ambiguity in the comment section is probably actually dealing with how this huge portion of memory is handled by python under the hood, and not IDLE.
EDIT 1:
I thing that what is happening, is that a mathematical expression evaluates to its answer, even when placed inside of a function that isn't called yet, only if the expression is self sufficient. This means that if a variable is used in the equation, the equation will be untouched in the byte code, and not evaluated until hard execution. The function has to be interpreted, and in that process, I think that your value is actually computed, resulting in the slower times. I am not sure about this, but I strongly suspect this behavior to be the root cause. Even if it is not so, you got to admit that 9<<(1<<26) kicks the computer in the behind, there's not much optimization that can be done there.
In[73]: def create_number():
return 9<<(1<<26)
In[74]: #Note that this seems instantaneous, but try calling the function!
In[75]: %timeit create_number()
#Python environment crashes because task is too hard
There is a slight deception in this kind of testing however. When trying this with the regular timeit, I got:
In[3]: from timeit import timeit
In[4]: timeit(setup = 'from __main__ import create_number', stmt = 'create_number()', number = 1)
Out[4]: .004942887388800443
Also keep in mind that printing the value is not do-able, so something like:
In[102]: 9<<(1<<26)
should not even be attempted.
For even more added support:
I felt like a rebel, so I decided to see what would happen if I timeit the raw execution of the equation:
In[107]: %timeit 9<<(1<<26)
10000000 loops, best of 3: 22.8 ns per loop
In[108]: def empty(): pass
In[109]: %timeit empty()
10000000 loops, best of 3: 96.3 ns per loop
This is really fishy, because apparently this calculation happens faster than the time it takes Python to call an empty function, which is obviously not the case. I repeat, this is not instantaneous, but probably has something to do with retrieving an already calculated object somewhere in memory, and reusing that value to calculate the expression. Anyways, nice question.
I am really puzzled. Here are more results with 3.4.1. Running either of the first two lines from the editor in either 3.4.1 or 3.3.5 gives the same contrast.
>>> a = 1 << 26; b = 9 << a # fast, , .5 sec
>>> c = 9 << (1 << 26) # slow, about 3 sec
>>> b == c # fast
True
>>> exec('d=9<<(1<<26)', globals()) # fast
>>> c == d # fast
True
The difference between normal execution and Idle's is that Idle exec's code in an exec call like the above, except that the 'globals' passed to exec is not globals() but a dict configured to look like globals(). I do not know of any 2.7 -- 3.4 difference in Idle in this respect except for the change of exec from statement to function. How can exec'ing an exec be faster than a single exec? How can adding an intermediate binding be faster?

Python - Tracking one little script with `pdb`

Is it possible save the evolution of constants of a program, a small one indeed, in one file ? In other word, is there a way to store the informations sent by pdb?
Suppose for example that we have the following code.
a = 1
b = 2
a = a + b
I would like to have something like the following.
a initialized to 1
b initialized to 2
a + b stored in a
I'm a little confused about what, exactly, you're asking. But it sounds like you want to implement logging.

Categories

Resources