By loading JSON from stdin before starting the REPL, I can pipe JSON outputs from other commands and work with the JSON data in Python.
I've tried something like and it worked:
kubectl get po -o json | cp /dev/stdin /tmp/data.json && python -i -c "import json; data = json.load(open('/tmp/data.json'))" && rm /tmp/data.json
Now I want to make it a script, so I write the following script:
#!/bin/bash -i
tmp_file=$(mktemp /tmp/ipyjson.XXXXXX)
cp /dev/stdin $tmp_file
python -i -c "import json; data = json.load(open('$tmp_file')); print(data)"
rm $tmp_file
And change the previous command to kubectl get po -o json | new_script.
But this time the REPL quits immediately after starting up, I have no idea what's the difference here. Maybe something about the interactive mode?
Edit:
I've also tried reading sys.stdin directly and met the same issue:
❯ k get po -o json | ipython -i -c "import sys, json; data = json.load(sys.stdin)"
Python 3.10.2 (main, Feb 11 2022, 14:13:20) [Clang 13.0.0 (clang-1300.0.29.30)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: Do you really want to exit ([y]/n)?
As you can see, ipython quited immediately with the prompt "Do you really want to exit ([y]/n)?".
Related
I want write a shell script that will run a Python Code stored in a shell variable $CODE.
#!/bin/bash
python3 $CODE
But this does not work, is there any way to do this? Any help is appreciated.The program that will be run:
print("Hello World")
export CODE='print("Hello World")'
Use the -c option.
python3 -c "$CODE"
python3 <<< "$CODE"
[Python.Docs]: Command line and environment - -c <command> states:
Execute the Python code in command. command can be one or more statements separated by newlines, with significant leading whitespace as in normal module code.
Example:
[064bit prompt]> CODE='import sys;print("Hello World");print(sys.version)'
[064bit prompt]> python -c "${CODE}"
Hello World
3.8.10 (default, Jun 22 2022, 20:18:18)
[GCC 9.4.0]
But this comes with some limitations. I'd save the code in a script and run that instead.
I would like to pipe some data into the ipython terminal client, run a command, and then stay in the session.
In terms of passing an argument into IPython, running a command, and keeping the session alive, this works:
[~]$ ipython -i -c "import sys; print(sys.argv[-1])" "my,testcsv\n1,2,3"
Python 3.7.3 (default, Mar 27 2019, 16:54:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.23.1 -- An enhanced Interactive Python. Type '?' for help.
my,test,csv\n1,2,3
In [1]:
But adding a pipe both raises an exception in Python and immediately quits back to the shell:
[~]$ echo "my,test,csv\n1,2,3" | ipython -i -c "import sys; print(sys.argv[-1])"
Python 3.7.3 (default, Mar 27 2019, 16:54:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.23.1 -- An enhanced Interactive Python. Type '?' for help.
import sys; print(sys.argv[-1])
In [1]: File "<ipython-input-1-f826f34ba2b7>", line 1
my,test,csv\n1,2,3
^
SyntaxError: unexpected character after line continuation character
In [2]: Do you really want to exit ([y]/n)?
[~]$ ^
And using xargs processes the input correctly, but it also immediately quits back to the shell:
[~]$ echo "my,test,csv\n1,2,3" | xargs -0 ipython -i -c "import sys; print(sys.argv[-1])"
Python 3.7.3 (default, Mar 27 2019, 16:54:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.23.1 -- An enhanced Interactive Python. Type '?' for help.
my,test,csv\n1,2,3
In [1]: Do you really want to exit ([y]/n)?
[~]$
Is there a way to accomplish what I'm after here?
I think it's exiting when it reads EOF from stdin. true | ipython -i also exits immediately. For that matter, so does true | python -i.
Instead you could use process substitution to get the command's stdout as a file.
tmp.py:
import sys
fname = sys.argv[-1]
with open(fname) as f:
print(f.read())
$ ipython --no-banner -i tmp.py <(echo "foo")
foo
In [1]:
This looks like a Python issue because using python print or call subprocess with cmd echo, I can get different results.(See examples in below)
The question is how to properly print wide chars in cmd.exe under chcp65001?
Is there an option in python print method or any special methods I need to do to adapt the Windows environment.
OS Win7 64bit.
==GOOD==
C:\>python -c "import subprocess; subprocess.run('cmd.exe /c echo 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊', shell=True)"
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
==BAD==
C:\> python -c "print('啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊')"
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
�啊啊啊啊啊啊啊啊啊啊啊
��啊啊啊啊啊啊
�啊啊啊
�啊
C:\>chcp
Active code page: 65001
C:\>python -V
Python 3.5.2
There is already a Perl base fix:
C:\>python -c "print('啊啊啊啊啊啊啊啊啊啊啊啊啊')" | perl -Mutf8 -ne "BEGIN{binmode(STDIN,':unix:encoding(utf8):crlf');binmode(STDOUT, ':unix:encoding(utf8):crlf');}print"
啊啊啊啊啊啊啊啊啊啊啊啊啊
C:\>chcp
Active code page: 65001
Why am I getting the last octet repeated when my Perl program outputs a UTF-8 encoded string in cmd.exe?
It would be good to have the Python Solution
I'm trying to execute shell-script with sarge library.
My file script.sh has this content:
#!/usr/bin/env sh
export LOCAL_PROJECT_ROOT=/path/to/the/dir
inotifywait -mr --exclude '(.git|.idea|node_modules)' \
-e modify,create,delete ${LOCAL_PROJECT_ROOT} --format '%w%f'
And I run it like with sarge:
sarge.run('sh script.sh')
I see with htop that no inotifywait process is running.
However, when I run this script directly in the shell with sh script.sh, everything works as expected.
If I remove --exclude and --format parts which both contain quoted arguments, sarge runs fine too.
It runs fine with sarge too if I rewrite the script into something like this:
echo "inotifywait -mr --exclude '(.git|.idea|node_modules)' -e modify,create,delete ${LOCAL_PROJECT_ROOT} --format '%w%f'" | /bin/sh
Sound like Module issue.
Because :
Python 2.7.6 (default, Nov 23 2017, 15:49:48)
[GCC 4.8.4] on linux2
Type "copyright", "credits" or "license()" for more information.
>>> 'a' == "a"
True
>>> '%s' %"'a'"
"'a'"
>>> "%s" %'"a"'
'"a"'
>>>
Maybe :
#!/usr/bin/env sh
export LOCAL_PROJECT_ROOT=/path/to/the/dir
inotifywait -mr --exclude "(.git|.idea|node_modules)" -e modify,create,delete ${LOCAL_PROJECT_ROOT} --format "%w%f"
Escaping character is undefined '\' check this
Next line character is \n, but you got "\\n"
You only run inotifywait -mr --exclude '(.git|.idea|node_modules)'
That's not enough for Shell.
I have a native program written in Python that expects its input on stdin. As a simple example,
#!python3
import sys
with open('foo.txt', encoding='utf8') as f:
f.write(sys.stdin.read())
I want to be able to pass a (PowerShell) string to this program as standard input. Python expects its standard input in the encoding specified in $env:PYTHONIOENCODING, which I will typically set to UTF8 (so that I don't get any encoding errors).
But no matter what I do, characters get corrupted. I've searched the net and found suggestions to change [Console]::InputEncoding/[Console]::OutputEncoding, or to use chcp, but nothing seems to work.
Here's my basic test:
PS >[Console]::OutputEncoding.EncodingName
Unicode (UTF-8)
PS >[Console]::InputEncoding.EncodingName
Unicode (UTF-8)
PS >$env:PYTHONIOENCODING
utf-8
PS >python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())"
´╗┐?
PS >chcp 1252
Active code page: 1252
PS >python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())"
?
PS >chcp 65001
Active code page: 65001
PS >python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())"
?
How can I fix this problem?
I can't even explain what's going on here. Basically, I want the test (python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())") to print out a Euro sign. And to understand why, I have to do whatever is needed to get that to work :-) (Because then I can translate that knowledge to my real scenario, which is to be able to write working pipelines of Python programs that don't break when they encounter Unicode characters).
Thanks to mike z, the following works:
$OutputEncoding = [Console]::OutputEncoding = (new-object System.Text.UTF8Encoding $false)
$env:PYTHONIOENCODING = "utf-8"
python -c "print('\N{Euro sign}')" | python -c "import sys; print(sys.stdin.read())"
The new-object is needed to get a UTF-8 encoding without a BOM. The $OutputEncoding variable and [Console]::OutputEncoding both appear to need to be set.
I still don't fully understand the difference between the two encoding values, and why you would ever have them set differently (which appears to be the default).