I have a python script file that works perfectly when I use it from the terminal.
Now I have created the following .desktop file in order to launch it easily:
[Desktop Entry]
Name=Test
GenericName=Test
Comment=My test script
Type=Application
Exec=/opt/test.py
Icon=/opt/test.png
Categories=Utils;
When I launch it the GTK window appear but clicking a button that call an init.d script make it working not properly.
Therefore adding Terminal=true make it working perfectly but I don't want to have that terminal open.
So I have then put the following code in order to log the environment variables:
import os
with open("/tmp/py_env.log", "w") as env_log:
env_log.write(str(os.environ))
and found differences.
So my question is how to write the .desktop file so that my application is running like if I start it from my terminal (without having an opened terminal :))
The problem is valid, but I think "replicating the terminal environment" is the wrong approach to solve it.
Indeed, what makes the application work is not the fact that it's launched from the terminal, it's that the terminal happens to have some environment variables which matter to your application.
Therefore, what you should aim for is to have those environment variables set properly at all times, rather than assuming the terminal environment will always happen to contain them all the time for all your users.
Thus, you should:
Check which environment variables are different between the two environments
Make a list of those which matter (i.e. those which would make the .desktop file work properly), and of what their value needs to be for the script to work
Either:
Create a wrapper script for your Python script, which initializes those environment variables properly, OR
Set those environment variables from inside the Python script itself.
this question is similar to .bashrc not read when shell script is invoked from desktop shortcut
either initialize your environment in ~/.bash_profile instead of
~/.bashrc
OR
make your *.desktop file call a wrapper that initializes your
environment - e.g. by sourcing ~/.bashrc (or whatever script is
responsible now).
the second solution is more specific (does not effect all other unrelated launches of your shell) in should thus be preferred.
Thanks anyone to have participate to this question.
I have solved this issue by implemented use of pkexec instead of gksudo.
pkexec seems to reuse the current user environment then I don't have this issue anymore.
Thanks.
Related
I just started using python and pycharm. I'm a bit confused of what is the run configuration in pycharm do and what is the different between the just run ?
A run configuration (not just in PyCharm, for example JetBrains IntelliJ also has them, in fact most IDEs have this concept) is a compilaton of settings to be used when running a program.
Let us stay with Python for the sake of simplicity. You might think that when you execute your script by typing in your command prompt...
python myscript.py
...that there are no settings or configuration involved. You are just running your script, right?
Not quite, you are in fact using what you could call an implicit run configuration, i.e. are whatever defaults and environment settings happen to take effect.
Some examples you will also find in PyCharm Python run configurations:
Script path is just the script you are calling, in the example myscript.py since we specified that on the command line.
Python interpreter is whatever Python interpreter is first in your path.
Parameters is empty in our example, as we didn't specify any on the command line.
Working directory is the current directory, where we are with our command prompt.
Enviromnent variables are those that happen to be set in our shell.
All of these and more can be defined in a run configuration (or multiple different run configurations if you need) for your project.
You can then select these conveniently from the dropdown menu, and the one currently selected will be used to execute your program when you press the green play button.
What is the difference between using a run configuration and just run in PyCharm?
If you just run your program, you are telling PyCharm that it should just use the project default configuration for the specific file type.
In other words, you are using a run configuration as well there, just the unmodified default configuration.
I will try to be brief!
For whatever reason, I couldn't make the entirety of my program in python, so I had to outsource one specific task to php (a language I do not know very well). As the python program runs, it is supposed to trigger the php program to run, and then do a few things afterwards which is not a problem.
It seems to me that, to be able to run something through python, you need it to be able to run through cmd first, and then you can make python use cmd to run the program. I had a few issues there, because the programs are on different drives, and the php program references other files and locations in the same directory and in sub-directories to where it is, this means I couldn't execute in one line of cmd, but first had to change directory, to then execute the php program from the folder it's in. Because my command wasn't just one line, I made a batch file containing all the steps.
My current working method is to open up cmd, change directory in cmd to where the php file is, and then run the php file. I had to add php to the "Environment Variable Path" to be able to do this. Here is the batch file that currently works when run by me:
cd /d C:
cd C:\Users\UserMain\Desktop\php\colorextract
php (2).php
When I double click this bat file, from my E drive, it successfully executes the php program. But when I tell python to execute the batch file, that is where things go wrong.
Here is my python code, apologies for the name of the bat file:
import os
os.system('cmd /k "bitch.bat"')
The resultant cmd window then goes thru the steps of the batch file: 1) it changes to the right directory, 2) it is unable to execute the php file because:
'php' is not recognised as an internal or external command, operable program or batch file.
Now, this is the standard error you get if you were to try running a php program without having added php to the "Environment Variable Path", I know this because I went through that same thing. But if I manually open a cmd window, not administrative or anything, I can 1) successfully perform the steps outlined in batch file, and program runs, and 2) I can even run the bat file, and that also runs the program.
The cmd window opened by python does not seem to be able to reference the "Environment Variable Path", or it is for another reason somehow handicapped against being able to do all the things that a normal cmd widow can. How can this be fixed?
Thanks in advance to anyone who reads this!
Edit: I found that python had not detected the changes I made to the environment variables the day before, hence why python's cmd was giving the exact error that not having php in the environment variable gives. After I restarted my computer, my code worked. Thank you to #Gerhard and #Aaron Junker for making me think much harder about this issue.
so I found a command that can be run after importing os.
print(os.environ)
I ran this, and it told me that Python could not see that php had been added to the environment variables, well, more likely that python did not have the most up to date information regarding what was in the path variable(s).
Restarting my computer made the changes kick in, and now my original code works. Whilst I do feel very stupid, I'm just happy that this is resolved.
This seems to me like both instances use different environment variables.
Open
System Properties -> Advanced -> environment variables and look that PHP is in the PATH variable in user variables and in System variables.
I have the following problem: I wrote a bash script for data analysis that works perfectly fine when I run it from the terminal. To further automate the process I wanted to use a python script that runs the bash script (using subprocess.call), changes the working directory, and reruns the script (and so on). This also worked fine when I did it on my MacBook. However, I need to do the analysis on a Linux machine and here the problem occurred. Again, running the script from the terminal worked fine but once I tried doing this with my python script it fails to find the relevant functions for the analysis. The functions are stored inside the anaconda3/bin folder.
(Python does not even find other functions like "pip")
Of course, I could add the path to all the functions in the bash script but this seems very inefficient to me. So my question is: is there any better way of telling python where to look for the functions? And can you maybe explain to me why running the script from the terminal works but not when I use subprocess.call?
Here is the python script:
import subprocess
import os
path_list = ["Path1",
"Path2"
]
for path in path_list:
os.chdir(path)
subprocess.call("Users/.../bash_script", shell=True)
I'm just posting my series of comments as an answer since I think this at least constitutes a reasonable answer for anyone running into a similar issue (your question could definitely be common enough to index from search engine results).
Issue:
...running the script from the terminal worked fine but once I tried doing this with my python script it fails to find the relevant functions for the analysis
In general, you can troubleshoot this kind of problem with:
import subprocess
subprocess.call('echo $PATH', shell=True)
If the directory that contains the relevant binaries/scripts/etc. is not in the output, then you are facing a PATH issue in the shell created by subprocess.call.
The exact problem as confirmed by the OP in comments is that anaconda3/bin is not part of your PATH. Your script works in a regular terminal session because of the Anaconda initialization function that gets added to your .bashrc when installing.
Part of an answer that is very helpful here: Python - Activate conda env through shell script
The problem with your script, though, lies in the fact that the .bashrc is not sourced by the subshell that runs shell scripts (see this answer for more info). This means that even though your non-login interactive shell sees the conda commands, your non-interactive script subshells won't - no matter how many times you call conda init.
Solution 1: Manually use the Anaconda sourcing function in your script
As the OP mentioned in the comments, their workaround was to use the initialization function added to their .bashrc in the script they are trying to run. Although this perhaps feels like not a great solution, this is a "good enough" workaround. Unfortunately I don't use Anaconda on Linux so I don't have an exact snippet of what this looks like. See the next section for a possibly "cleaner" solution.
Solution 2: Use bash -i to run your script
As mentioned in the same answer linked above, you might be able to use:
bash -i Users/.../bash_script
This will tell bash to run in interactive mode, which then properly sources your .bashrc file when creating the shell. As a result, Anaconda and related functions should work properly.
Solution 3: Manually add anaconda3/bin to PATH
You can check out this answer to decide if this is something you want to do. Keep in mind they are speaking about a Windows OS but most of the same applies to Linux.
When you add the directory to your PATH, you are specifically telling your system to always look in that directory for commands when executing by name, e.g. ping or which. This can have unexpected behavior if you have conflicts (e.g. a command is found with the same name in /usr/bin and .../anaconda3/bin), and as such Anaconda does not add its bin folder to your PATH by default.
This is not necessarily "dangerous" per se, it's just not an ideal solution for most people. However, you are the boss of your own system. If you decide this works for your particular workflow, you can just add the export to your script:
export PATH="path/to/anaconda3/bin:$PATH"
This will set the PATH for use in the current shell and sub-processes.
Solution 4: Manually source the conda script (possibly outdated)
As mentioned in this answer, you can also opt to manually source the conda.sh script (keep in mind your conda.sh might be in another directory):
source /opt/anaconda/etc/profile.d/conda.sh
This will essentially run that shell script and add the included functionality to the current shell (e.g the one spawned by subprocess.call).
Keep in mind this answer is quite a bit older (~2013) and may not apply anymore, depending how much conda has changed over the years.
Notes
As I mentioned in the comments, you may want to post some related questions on https://unix.stackexchange.com/. You have an interesting configuration challenge that may be better suited for answers specifically pertaining to Linux, since your issue is sourcing directly from Linux shell behavior.
I wrote a nice .bat file that runs a python script:
cd C:\ProgramData\Anaconda64\condabin
call conda activate
call conda activate py37_32
SET PyPathName=C:\ProgramData\Anaconda64\envs\py37_32\python.exe
SET ScriptName=C:\Users\%USERNAME%\path_to_my_script\my_script.py
%PyPathName% %ScriptName%
When I click on the .bat file, I get the expected result in the terminal window that opens up:
C:\Users\my_username\path_to_batfile>cd C:\ProgramData\Anaconda64\condabin
C:\ProgramData\Anaconda64\condabin>call conda activate
(base) C:\ProgramData\Anaconda64\condabin>call conda activate py37_32
(py37_32) C:\ProgramData\Anaconda64\condabin>SET PyPathName=C:\ProgramData\Anaconda64\envs\py37_32\python.exe
(py37_32) C:\ProgramData\Anaconda64\condabin>SET ScriptName=C:\Users\my_username\path_to_my_script\my_script.py
(py37_32) C:\ProgramData\Anaconda64\condabin>C:\ProgramData\Anaconda64\envs\py37_32\python.exe C:\Users\my_username\path_to_my_script\my_script.py
Everything is fine, the script works well and all. Except that I would like to interact with the results coming from the script, using python. Example: in the my_script.py script, I am receiving data from a websocket and storing it in a pandas time series. To give a concrete example, I'd like to type at any given moment:
my_series.plot()
This is a special case of something I'd like to do. But really, my question is rather general: is there any way I can type python code in the terminal window that opens up when running the bat file, such that I can use the results of the script?
I can provide additional details about the script itself.
EDIT:
It seems that there is some confusion in the way I phrased the question hence here a more specific solution taken from one of the comments.
How do I modify the bat file in such a way as the environment and console instance remains open upon the scripts completion?
Add a simple line:
cmd /k
This will open a new cmd instance (using the same window), which inherits the environment you just set, and will not close because of the /k. See cmd /? for details.
I am very new to Python and I have been trying to find a way to write in cmd with python.
I tried os.system and subprocess too. But I am not sure how to use subprocess.
While using os.system(), I got an error saying that the file specified cannot be found.
This is what I am trying to write in cmd os.system('cd '+path+'tesseract '+'a.png out')
I have tried searching Google but still I don't understand how to use subprocess.
EDIT:
It's not a problem with python anymore, I have figured out. Here is my code now.
os.system("cd C:\\Users\\User\\Desktop\\Folder\\data\\")
os.system("tesseract a.png out")
Now it says the file cannot be open. But if I open the cmd separately and write the above code, it successfully creates a file in the folder\data.
Each call to os.system is a separate instance of the shell. The cd you issued only had effect in the first instance of the shell. The second call to os.system was a new shell instance that started in the Python program's current working directory, which was not affected by the first cd invocation.
Some ways to do what you want:
1 -- put all the relevant commands in a single bash file and execute that via os.system
2 -- skip the cd call; just invoke your tesseract command using a full path to the file
3 -- change the directory for the Python program as a whole using os.chdir but this is probably not the right way -- your Python program as a whole (especially if running in a web app framework like Django or web2py) may have strong feelings about the current working directory.
The main takeaway is, os.system calls don't change the execution environment of the current Python program. It's equivalent to what would happen if you created a sub-shell at the command line, issued one command then exited. Some commands (like creating files or directories) have permanent effect. Others (like changing directories or setting environment variables) don't.