How to validate the syntax of a Python script? [duplicate] - python

This question already has answers here:
How can I check the syntax of Python script without executing it?
(9 answers)
Closed 6 years ago.
I just want the simplest possible way for my Python script to ask "is the Python code which I just generated syntactically valid Python?"
I tried:
try:
import py_compile
x = py_compile.compile(generatedScriptPath, doraise=True)
pass
except py_compile.PyCompileError, e:
print str(e)
pass
But even with a file containing invalid Python, the exception is not thrown and afterwards x == None.

There is no need to use py_compile. It's intended use is to write a bytecode file from the given source file. In fact it will fail if you don't have the permissions to write in the directory, and thus you could end up with some false negatives.
To just parse, and thus validate the syntax, you can use the ast module to parse the contents of the file, or directly call the compile built-in function.
import ast
def is_valid_python_file(fname):
with open(fname) as f:
contents = f.read()
try:
ast.parse(contents)
#or compile(contents, fname, 'exec', ast.PyCF_ONLY_AST)
return True
except SyntaxError:
return False
Be sure to not execute the file, since if you cannot trust its contents (and if you don't even know whether the file contains valid syntax I doubt you can actually trust the contents even if you generated them) you could end up executing malicious code.

Related

Cannot print data off a JSON file [duplicate]

This question already has answers here:
How should I write a Windows path in a Python string literal?
(5 answers)
Closed 6 months ago.
I have a JSON file called data.json and I am trying to print the data inside that JSON file. The JSON file got created by the command:
git log --pretty="format:{"commit":"%h", "merge":"%p", "author":"%an", "title":"%s", "body":"%b"}",>"C:\test_temp\data.json"
I am trying to print the data inside the file with the function parse_json but I am getting an error that says IOError: [Errno 22] invalid mode ('r') or filename "C:\test_temp\data.json"
json_directory = "C:\test_temp\data.json"
def parse_json_file(json_directory):
with open(json_directory) as f:
data = json.load(f)
print(data)
The json file is already there but I am not sure why it cannot read that file.
Also the data that got generate from the JSON file does not have proper formatting as the dictionary is not surrounded by the " " even though I indicated it in the executed git log command. Will that cause a problem if I try to parse the json file.
Maybe try:
json_directory = "C:\\test_temp\\data.json"
Your command is producing invalid json, so your json.load method call will never succeed.
You need to escape the quotes-- what you have supplied (as you can see from stack overflow's syntax highlighting) is actually a series of strings which your shell is concatenating together.
In BASH on OSX, escaping the strings looks like:
git log --pretty="format:{\"commit\":\"%h\", \"merge\":\"%p\", \"author\":\"%an\", \"title\":\"%s\", \"body\":\"%b\"}"
You could also enclose the entire argument to pretty with single quotes, as follows:
git log --pretty='format:{"commit":"%h", "merge":"%p", "author":"%an", "title":"%s", "body":"%b"}',>"C:\test_temp\data.json"
Once your json generation command is corrected, I suspect your script will succeed so long as the paths are correct.
If you try to correct the command as I have recommended and it does not work, please post the JSON file you are generating, as well as the shell you are using.

The open() functions doesn't behave correctly with filepath containing special characters

I'm writing this simple code:
file = input('File to read: ')
fhand = open(file, 'r')
The file I want to open is called 'test.txt', and it is located in a subfolder; what I put into the requested input therefore is: 'DB\test.txt'.
Well: it doesn't work, returning this error message:
OSError: [Errno 22]Invalid argument: 'DB\test.txt'.
I have another file in the same directory, called 'my_file.txt', and I don't get errors attempting to open it. Lastly I have another file, called 'new_file.txt', and this one also gets me the same error.
What seems obvious to me is that the open() function reads the "\t" and the "\n" as if they were special characters; searching on the web I found nothing that really could help me avoiding special characters within user input strings...
Could anybody help?
Thanks!
you'll have no problems with Python 3 with your exact code (this issue is often encountered when passing windows literal strings where the r prefix is required).
With python 2, first you'll have to wrap your filename with quotes, then all special chars will be interpreted (\t, \n ...). Unless you input r"DB\test.txt" using this raw prefix I was mentionning earlier but it's beginning to become cumbersome :)
So I'd suggest to use raw_input (and don't input text with quotes). Or python version agnostic version to override the unsafe input for python 2 only:
try:
input = raw_input
except NameError:
pass
then your code will work OK and you got rid of possible code injection in your code as a bonus (See python 2 specific topic: Is it ever useful to use Python's input over raw_input?).

how to create empty file in python [duplicate]

This question already has answers here:
Create empty file using python [duplicate]
(2 answers)
Closed 5 years ago.
I would like to create an empty file in Python. But I have difficulty creating one..Below is the Python code I used to create but it gives me error:
gdsfile = "/home/hha/temp.gds"
if not (os.path.isfile(gdsfile)):
os.system(touch gdsfile)
Error I got:
File "/home/hha/bin/test.py", line 29
os.system(touch gdsfile)
^
SyntaxError: invalid syntax
But from the command line, I am able to create new file using: touch
Thank you very much for your help
Howard
First you have a syntax error because os.system() expects a string argument and you have not provided one. This will fix your code:
os.system('touch {}'.format(gdsfile))
which constructs a string and passes it to os.system().
But a better way (in Python >= 3.3) is to simply open the file using the open() builtin:
gdsfile = "/home/hha/temp.gds"
try:
open(gdsfile, 'x')
except FileExistsError:
pass
This specifies mode x which means exclusive creation - the operation will fail if the file already exists, but create it if it does not.
This is safer than using os.path.isfile() followed by open() because it avoids the potential race condition where the file might be created by another process in between the check and the create.
If you are using Python 2, or an earlier version of Python 3, you can use os.open() to open the file with the exclusive flag.
import os
import errno
gdsfile = "/home/hha/temp.gds"
try:
os.close(os.open(gdsfile, os.O_CREAT|os.O_EXCL))
except OSError as exc:
if exc.errno != errno.EEXIST:
raise

Checking Python Syntax, in Python

I would like to know if it's possible to check if a Python code has a correct syntax, without running it, and from a Python program. The source code could be in a file or better in a variable.
The application is the following: I have a simple text editor, embedded in my application, used for editing Python scripts. And I'd like to add warnings when the syntax is not correct.
My current idea would be to try importing the file and catch a SyntaxError exception that would contains the erroneous line. But I don't want it to execute at all. Any idea?
That's the job for ast.parse:
>>> import ast
>>> ast.parse('print 1') # does not execute
<_ast.Module at 0x222af10>
>>> ast.parse('garbage(')
File "<unknown>", line 1
garbage(
^
SyntaxError: unexpected EOF while parsing
I just found out that I could probably use the compile function. But I'm open to better suggestions.
import sys
# filename is the path of my source.
source = open(filename, 'r').read() + '\n'
try:
compile(source, filename, 'exec')
except SyntaxError as e:
# do stuff.
You could use PyLint and call it when the file is saved, and it'll check that file for errors (it can detect much more than just syntax errors, look at the documentation).

Taking String arguments for a function without quotes

I've got a function meant to download a file from a URL and write it to a disk, along with imposing a particular file extension. At present, it looks something like this:
import requests
import os
def getpml(url,filename):
psc = requests.get(url)
outfile = os.path.join(os.getcwd(),filename+'.pml')
f = open(outfile,'w')
f.write(psc.content)
f.close()
try:
with open(outfile) as f:
print "File Successfully Written"
except IOError as e:
print "I/O Error, File Not Written"
return
When I try something like
getpml('http://www.mysite.com/data.txt','download') I get the appropriate file sitting in the current working directory, download.pml. But when I feed the function the same arguments without the ' symbol, Python says something to the effect of "NameError: name 'download' is not defined" (the URL produces a syntax error). This even occurs if, within the function itself, I use str(filename) or things like that.
I'd prefer not to have to input the arguments of the function in with quote characters - it just makes entering URLs and the like slightly more difficult. Any ideas? I presume there is a simple way to do this, but my Python skills are spotty.
No, that cannot be done. When you are typing Python source code you have to type quotes around strings. Otherwise Python can't tell where the string begins and ends.
It seems like you have a more general misunderstanding too. Calling getpml(http://www.mysite.com) without quotes isn't calling it with "the same argument without quotes". There simply isn't any argument there at all. It's not like there are "arguments with quotes" and "arguments without quotes". Python isn't like speaking a natural human language where you can make any sound and it's up to the listener to figure out what you mean. Python code can only be made up of certain building blocks (object names, strings, operators, etc.), and URLs aren't one of those.
You can call your function differently:
data = """\
http://www.mysite.com/data1.txt download1
http://www.mysite.com/data2.txt download2
http://www.mysite.com/data3.txt download3
"""
for line in data.splitlines():
url, filename = line.strip().split()
getpml(url, filename)

Categories

Resources