Create and run Python program with a Python program - python

This is my first time using Python and I'm trying to create a program that can:
Create a new Python program in IDLE
Make the new program contain the print command - print('Hello, world!')
Save the program and run it
Exit IDLE
This is the code I have so far. It doesn't seem to be creating the file, and I might have made some other mistakes that I don't know about.
import sys
name = input('C:\\MyFolder\\program.py')
//Create program containing print command
file = open(name, 'w')
file.write("print('Hello, world!')")
file.close()
//Run program (and possibly save it?)
os.system('C:\\MyFolder\\program.py')
//Exit IDLE
sys.exit(0)
How do I create, write to and run the new program?

Although it isn't entirely clear from your question, I think I know what your problem is.
First, when you do input('C:\\MyFolder\\program.py'), that C:\\MyFolder\\program.py is just the prompt that gets displayed to the user. It's not a default value. So, if the user just hits return, name is going to be empty, and you're not going to successfully create a file.
Second, even if the user does type something, unless what he types is exactly C:\\MyFolder\\program.py, you're creating a file with one name, then trying to run a file with a different name, which isn't going to work.
So, you probably want something like this:
default_name = 'C:\\MyFolder\\program.py'
name = input(default_name)
if not name:
name = default_name
# ... your existing code to create the file
os.system(name)
There are a lot of ways you could improve this (use subprocess.check_call with sys.executable, add a shbang line to the file, use a with statement instead of explicit close, make the prompt look something like Filename (default C:\MyFolder\program.py)? instead of just the default value, …). But this should be enough to get it working.

Related

How do I call a function in vs code using python?

I'll want to know how to call a function in vs code. I read the answer to similar questions, but they don't work:
def userInput(n):
return n*n
userInput(5)
And appends nothing
def Input(n):
return n*n
And in the terminal:
from file import *
from: can't read /var/mail/file
Can somebody help me?
You are doing everything correctly in the first picture. In order to call a function in python on vs code you first have to define the function, which you did by typing def userInput(n):. If you want to see the result of your function, you should not use return, you should use print instead. Return is a keyword- so when your computer reaches the return keyword it attempts to send that value from one point in your code to another. If you want to see the result of your code, typing print (n) would work better.
Your code should look like this:
def userInput(n):
print (n * n)
userInput(5)
The code would print the result 25
Your terminal is your general way to access your operating system, so you have to tell it that you want it to interpret your Python code first.
If you want to run the file you're typing in, you have to first know the location of that file. When you type ls in your terminal, does the name of your Python file show up? If not, hover over the tab in VSCode (it's close to the top of the editor) and see what path appears. Then in your terminal type cd (short for "change directory") and then the path that you saw, minus the <your filename here>.py bit. Type ls again, and you should see your Python file. Now you can type python <your filename here>.py to run it (provided you have Python installed).
You could also run the IDLE by just typing python in your terminal. This will allow you to write your code line-by-line and immediately evaluate it, but it's easier to write in VSCode and then run it with the method I described before.

Running python script through PHP script not working

So basically, I am trying to run some preliminary tests for a website I will be building.
There will be downloads through the site, possibly for the same resource by different users, possibly nearly or at the same time. I want to implement a lock manager of sorts to prevent repeated downloads of a resource when one is already in progress.
The test I am running is just to see if this is even possible. What I am specifically testing for right now is if I begin running a program, if I attempted to open the program again would it open a completely new instance or go to the already open instance. I am doing to this to try and see if user 1 makes changes in their program, if the second user opens their program, they will see those change; otherwise they might not see the changes if they open up a completely new instance of a program.
PHP
exec(escapeshellcmd("C:\Program Files\Python 3.7\python.exe Test2Php.py 0 Testing"), $o1, $r);
echo $r;
var_dump($o1);
Python
#!/usr/bin/env python
import sys
arr = []
t = sys.argv[1]
if (t == '0'):
arr = [sys.argv[k] for k in range(2, len(sys.argv))]
print("if")
else:
print(str(len(arr)))
The problem is the script doesn't return any output at all! It doesn't run either. I tested this by having the python program write a file at the end of successful execution. I have tried shell_exec, passthru, etc. The program itself works when run through command line, but not in any scripts I have made.
I am using a WAMP server on windows.
EDIT:
For anyone else dealing with this. Make sure you have the default Python package in your system path variable. You can do this easily by installing the latest version of python and choosing add to system path. Uninstall anaconda or whatever else may be in the way of the system path and enjoy.
Also make sure you find where the python exe is and use the full path to it.
Your list comprehension will get out of range since you can never do lst[len(lst)] without getting an IndexError. The str() wrapper isn't necessary to print len(arr).
Instead, use a slice of [:2] to remove the first 2 elements:
#!/usr/bin/env python
import sys
arr = []
t = sys.argv[1]
if t == '0':
arr = sys.argv[2:]
print("if")
else:
print(len(arr))

python script that takes command line arguments needs to be called from another python script

I completely understand that I should have written the script right the first time, but the fact is I have a script that generates a data file based upon two values passed to it from the command line- like this:
[sinux1~]: ./sim_gen.py 100 .3
I need to call this script from within another script, iterating over a range of values. I searched around and after navigating through all of the "you shouldn't," I tried :
exec(open("./sim_gen.py 100 .3").read())
And this doesn't seem to work.
Help?
Let's break this down into pieces:
exec(open("./sim_gen.py 100 .3").read())
This is equivalent to:
f = open("./sim_gen.py 100 .3")
contents = f.read()
exec(contents)
That open is the same open you use for, say, reading a text file or a CSV. You're asking for a file named "sim_gen.py 100 .3" in the current directory. Do you have one? Of course not. So the open fails.
The best solution is, as you already know, to rewrite sim_gen.py so that you can import it and call a function and pass the arguments to it.
Failing that, the cleanest answer is probably to just run the Python script as a subprocess:
import subprocess
import sys
subprocess.run([sys.executable, "./sim_gen.py", "100", ".3"])
Notice that this is effectively the same thing you're doing when you run the script from your shell, so if it was OK there, it's almost surely OK here.
If you really need to exec for some reason, you will need to do something really hacky, and temporarily change argv for that script's code:
import sys
_argv = sys.argv
try:
sys.argv = ["./sim_gen.py", "100", ".3"]
with open("./sim_gen.py 100 .3"):
exec(f.read())
finally:
sys.argv = _argv
Although really, unless the point of running this is to silently modify your own module's globals or the like, you (a) almost certainly don't really need exec, and (b) want to pass an explicit globals argument even if you do really need it.

Python; how to properly call another python script as a subprocess

I know a very similar question has already been asked but since none of the solutions posted there worked for my problem I try to make it replicable:
So I'm calling this script to merge some shapefiles (all files in one folder) like this:
shpfiles = 'shapefile_a.shp shapefile_b.shp'
subprocess.call(['python', 'shapemerger.py', '%s' % shpfiles])
I only get the Usage Instructions from the script so I cant determine what goes wrong. If i call the script directly in the terminal it works.
Any help is appreciated.
Every time a program is started, it receives a list of arguments it was invoked with. This is often called argv (v stands for vector, i.e. one-dimensional array). The program parses this list, extracts options, parameters, filenames, etc. depending on its own invocation syntax.
When working at the command line, the shell takes care of parsing the input line, starting new program or programs and passing them their argument list.
When a program is called from another program, the caller is responsible to provide the correct arguments. It could delegate this work to shell. The price for it is very high. There is substantial overhead and possibly a security risk! Avoid this approach whenever possible.
Finally to the question itself:
shpfiles = 'shapefile_a.shp shapefile_b.shp'
subprocess.call(['python', 'shapemerger.py', '%s' % shpfiles])
This will invoke python to run the script shapemerger.py with one argument shapefile_a.shp shapefile_b.shp. The script expects filenames and receives this one name. The file "shapefile_a.shp shapefile_b.shp" does not exist, but the script probably stops before attempting to access that file, because it expect 2 or more files to process.
The correct way is to pass every filename as one argument. Assuming shpfiles is a whitespace separated list:
subprocess.call(['python', 'shapemerger.py'] + shpfiles.split())
will generate a list with 4 items. It is important to understand that this approach will fail if there is a space in a filename.

Value Error: need more than 1 value to unpack

I have looked at the suggested similar questions and whilst useful, do not actual match my problem and I'm still struggling.
I am using a batch file to run a series of python files, and one of these python scripts returns a variable to be used as an argument in a later script (it has to be exported to console because it is also used as a parameter in an executable.)
By batch file looks like this:
#echo off
#title AutoStats
set raw_dir ='raw_directory'
set today_dir ='today_directory'
set archive_dir='archive_directory'
set error_file='error_directory'
set DateEstate='dE'
set OTQ_File='OTQ_File'
cd C:\dev\OTQtxt
for /f "delims=" %%a in ('get_date.py') do set $date=%%a
python create_csv.py %$date% %raw_dir% %archive_dir% %error_file%
pause
The python script looks like this:
from sys import argv
date, raw_dir, today_dir, archive_dir, error_file = argv[1:]
print date
print raw_dir
print today_dir
print archive_dir
print error_file
The reason for using argv[1:] is because I don't want to use the script name as an argument
In the future it will obviously do more than this, this is just for testing whether I can get the arguments in.
The error is as the title states. This only occurs when running it from the batch file, if I run it from powershell and type in the arguments myself then it works.
I find it odd that when typing the arguments myself in powershell the script works fine, when using the parameters set in the .bat it returns an error.
Can anybody shed some light on why this might be. I've never used batch files until now so it might just be a simple mistake.
Whilst the problem pointed out by Ffisegydd was correct, the real mistake causing the problem to happen with a different number of argument was with with setting of parameters in the batch file.
for the first 2 set lines I added a space after the parameter name:
set today_dir ='today_directory'
should have been:
set today_dir='today_directory'

Categories