Using "konsole" command to run python script - python

I'm trying to, from a command line, open an instance of konsole and run a python script. I'm trying:
konsole -hold -e 'python -i hello.py'
The behaviour I'm getting is that a persistent konsole opens, and I am dropped into python, but the script does not run.
Python 2.7.2+ (default, Oct 4 2011, 20:03:08)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
What do I need to do to get the python script to run in the konsole window?

jsbueno's solution is the correct one. However, as described here, you can also do something like this ...
konsole --hold -e /bin/sh -c "python -i hello.py"
P.S. you'll need to specify --workdir (before the -e arg), or provide the full path to the python script, if it's not always in the initial working dir of konsole. But, you probably already knew that.

The problem is the way "konsole" uses the parameters after the -e switch - it seems like it simply pass them in a call that does not interpret the space separators as parameter separators.
However, if you don't put your call parameters inside quotes it will work - that is, simply:
konsole --hold -e python -i hello.py
(I just tested it here)

Related

Self invocation of interactive shell through Python3 with bash

I am using python3 and subprocess.Popen to spawn a process of bash and invoking the Python3 interpreter again through the standard interpreter.
bash -i states:
-s If the -s option is present, or if no arguments remain after
option processing, then commands are read from the standard
input. This option allows the positional parameters to be
set when invoking an interactive shell.
This is a minimized example but it mainly bakes down to the following code:
import subprocess
import sys
p = subprocess.Popen(["bash", "-s"], stdin=subprocess.PIPE,stderr=sys.stderr, stdout=sys.stdout)
p.stdin.write(b"python3\n")
p.stdin.flush()
print("Done")
The output is simply "Done". Any suggestions how I need to handle the stdin pipes in order to let the interactive shell pop up inside the newly executed python3 interpreter?
Actual output
% python3 test.py
Done
Expected output:
% python3 test.py
Python 3.10.8 (main, Oct 13 2022, 10:17:43) [Clang 14.0.0 (clang-1400.0.29.102)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

Newline character written to file with echo works in shell, but literal in Python 3

I'm on a Ubuntu 20.04 system, and I'm using Python 3.8 to write a script that does multiple things using configurable lines of bash, but one of them is that it creates desktop shortcuts.
This single-line command creates a desktop shortcut, and works flawlessly when I execute it directly in my terminal:
echo "[Desktop Entry]"$'\n'"Type=Application"$'\n'"Name[en_US]=Documents"$'\n'"Exec=pcmanfm ~/Documents"$'\n'"Icon=system-file-manager" > ~/Desktop/1;
However, when I execute it in Python, like so:
foobar.py
rl = """echo "[Desktop Entry]"$'\n'"Type=Application"$'\n'"Name[en_US]=Documents"$'\n'"Exec=pcmanfm ~/Documents"$'\n'"Icon=system-file-manager" > ~/Desktop/1;"""
subprocess.run(rl, shell=True)
...instead of creating a desktop shortcut with the proper name, icon, and action, it creates an empty file that contains the following text:
0.txt:
[Desktop Entry]$\nType=Application$\nName[en_US]=Sign Out$\nExec=/home/agent/QaSC/login/login.bin$\nIcon=system-switch-user
Is there any particular reason why Python would be handling the newline characters differently than the bash shell does, and if so, how can I resolve this problem?
$'...' is a bash extension, but the default shell used when shell=True is specified is sh. Use the executable option to specify an alternate shell.
subprocess.run(rl, shell=True, executable='/bin/bash')
Since the argument to echo has quotes, it could contain literal newlines at the command line, and therefore also in the Python process. I see no reason to use the Bash extension $'\n' syntax.
$ echo "foo
> bar"
foo
bar
$ python
Python 3.8.10 (default, Mar 15 2022, 12:22:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.run('echo "foo\nbar"', shell=True)
foo
bar
CompletedProcess(args='echo "foo\nbar"', returncode=0)
>>>
(It's also unclear why the Python code doesn't just write a file in the normal way, but I assume the command in the OP is essentially a placeholder.)

How to correctly parse a Git command (`git log ...`) in Python?

Using a Python script, I'd like to get the email of a person who last committed changes to a specific file /path/to/file.py.
Sounds easy, right? I just need to somehow parse the following
git log -n 1 --pretty=format:%ae -- /path/to/file.py
Package sh is my preferred choice. Unfortunately, in Python
import sh
print(str(sh.git.log('-n 1 --pretty=format:%ae -- /path/to/file.py')))
print(str(sh.git.log('-n', '1', '--pretty=format:%ae', '--', /path/to/file.py')))
both print - (press RETURN).
So maybe I'm messing something up with the arguments.
Otherwise, str(sh.git.status()) correctly returns On branch master ..., and some other tested commands work as expected.
How to solve this?
The - (press RETURN) output sounds like it's something printed by a pager.
Remember, every Git command may (depending on options, arguments, configuration settings, and other environmental details such as whether stdin is a tty) run its output through a pager. The pager used depends on your personal configuration. How that pager acts depends on the pager used and on the input data.
One simple workaround is to run git --no-pager <git-command> to tell Git not to use a pager, even if the configuration and environment suggest that Git should use a pager.
This should work:
print(str(sh.git.log("-n 1", "--pretty=format:%ae", "/path/to/file")))
At least this shows how it works on my machine:
$ git log -n 1 --pretty=format:%ae -- README.md
foo#bar.com
$ python3
Python 3.6.4 (default, Jan 25 2018, 15:54:40)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sh
>>> print(str(sh.git.log("-n 1", "--pretty=format:%ae", "README.md")))
foo#bar.com

Running Python interpreter inside Python interpreter: Explain behavior

While fooling around with the OS module in the python interpreter (run inside the shell on a Linux system), I noticed it is possible to do the following:
>>> os.system("python") #execute run python command in enclosing shell
Producing the following output, indicating a new python REPL session:
Python 2.7.9 (default, Apr 2 2015, 15:34:55)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> #*blinking cursor*
From here, its possible to once again make a system call to start a new session of Python, from which I can make the system call again, etc. These Python environments seem independent from each other in that variables aren't shared amongst sessions and that the system calls are treated equivalently.
These sessions seem to run inside each other, at least to some extent, rather than in parallel, as evidenced by the outcome of the quit() function:
>>> os.system("python")
Python 2.7.9 (default, Apr 2 2015, 15:34:55)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()
0
>>> quit()
0
>>> quit()
0
>>> quit()
shaked#shaked-ThinkPad-X220:~/Desktop$ python
Yet, a quick examination (>>> os.system("ps -e")) of the ongoing processes from the shell reveals a new sh for each python interpreter running:
11802 ? 00:00:00 kworker/u16:0
11803 pts/3 00:00:00 sh
11804 pts/3 00:00:00 python
11806 pts/3 00:00:00 sh
11807 pts/3 00:00:00 python
11810 pts/3 00:00:00 sh
11811 pts/3 00:00:00 python
11813 pts/3 00:00:00 sh
11814 pts/3 00:00:00 ps
Can anyone explain this (seemingly) strange behaviour in terms of underlying system processes? That is, are these sessions running in parallel or from within each other?
Apologies if this question has come up before, but I wasn't sure how others might have presented it.
When you use os.system, it performs the command in a subshell, something like /bin/sh -c 'yourcommand'*. Thus, it's completely sensible that you would get the behavior you describe. It's not different from running:
/bin/sh -c 'python'
in any shell.
*with mild differences on Windows, please read the documentation.
As per the documentation of os.system():
Execute the command (a string) in a subshell.
os.system() forks, executes a subshell passing the argument to this subshell and waits for the subshell to exit.
The subshell executes the command and waits for it to terminate, hence the process tree is:
- python
\-- sh
\-- python
\-- sh
\-- python
Python's os.system starts a new system process. When you pass "python" to it, it starts a new Python interpreter, that is independent from the one os.system was called from.

How to set system variable on mac? Since i could not get the system variable by using python 3 os.getenv or os.environ

I am pretty sure i've set the system variable as following:
echo 'export TEST=/path/test' >> .bash_profile
echo 'export TEST=/path/test' >> .zshrc
And it is possible to get the variable from terminal just like:
echo $TEST
#the '/path/test' was print out
But i could not get it from python 3, as following:
TEST = os.getenv('TEST')
or
TEST = os.environ['TEST']
Does anyone know why? Any clue would be appreciated
You seem to be confused by the distinction between environment variables and (as you put it) system variables. When you run
echo 'export TEST=/path/test' >> .bash_profile
echo 'export TEST=/path/test' >> .zshrc
What you are doing is setting environment variables. What happens is that when you start a shell subsystem, the OS calls certain startup files to set variables for your environment. If you are in a Bash shell, it will call .profile, .bash_profile, etc. When you get your shell, any variables you set in your startup scripts are set for your environment. So for instance:
pswaminathan ~ $ export TEST=/path/test
pswaminathan ~ $ python3
Python 3.4.0 (default, Mar 24 2014, 00:31:02)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getenv('TEST')
'/path/test'
But $TEST here is not set up at the system level. It is set up at the environment level. It relies on being set; in your case, by the .zshrc or .bash_profile file. If you are running a script by cron, for example, you can set your environment varaibles in the crontab. Or you can set your envvars in a shell script you're using to run these. So how are you running this file, where you're not getting the right environment variables?
Also good reference: http://en.wikipedia.org/wiki/Environment_variable

Categories

Resources