Is there a way to avoid a new line while using `end=` - python

I've just started using python and I'm creating a simple program that will ask whoever the user is a question and then from the text file I will extract a specific line and print that line and along with the line - at the end I will add their answer. here's the code.
question = input("do you want to print the line")
if "yes" in question:
print(open("tp.txt").readlines()[:10][-1],end=question)
The issue is that ,end=question) puts the users answer on a new line. I know that end= is the same as \n. So I'm just wondering is there a way or an alternative to stop 'end=' from automatically creating a new line?
print(open("tp.txt").readlines()[:10][-1],
is the way I open and read a specific line from the file
since its a 'nice' shortcut to do than rather dowith open (filename.txt,'r') as f:

The problem is that the lines returned by readlines() contain the ending newline:
$ echo 'a
> b
> c
> ' > test_file.txt
$ python3
Python 3.5.2 (default, Jul 5 2016, 12:43:10)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> with open('test_file.txt') as f:
... print(f.readlines())
...
['a\n', 'b\n', 'c\n', '\n']
See the \n? Note the difference bewteen:
>>> print('a\n')
a
>>>
And:
>>> print('a')
a
>>>
So you want to remove that:
>>> with open('test_file.txt') as f:
... for line in f:
... print(line.rstrip('\n'), end='<something>')
...
a<something>b<something>c<something><something>>>>

Related

Getting csv.Sniffer to work with quoted values

I'm trying to use python's CSV sniffer tool as suggested in many StackOverflow answers to guess if a given CSV file is delimited by ; or ,.
It's working fine with basic files, but when a value contains a delimiter, it is surrounded by double quotes (as the standard goes), and the sniffer throws _csv.Error: Could not determine delimiter.
Has anyone experienced that before?
Here is a minimal failing CSV file:
column1,column2
0,"a, b"
And the proof of concept:
Python 3.5.1 (default, Dec 7 2015, 12:58:09)
[GCC 5.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import csv
>>> f = open("example.csv", "r")
>>> f.seek(0);
0
>>> csv.Sniffer().sniff(f.read(), delimiters=';,')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/csv.py", line 186, in sniff
raise Error("Could not determine delimiter")
_csv.Error: Could not determine delimiter
I have total control over the generation of input CSV file; but sometimes it is modified by a third party using MS Office and the delimiter is replaced by semicolumns, so I have to use this guessing approach.
I know I could stop using commas in the input file, but I would like to know if I'm doing something wrong first.
You are giving the sniffer too much input. Your sample file does work if you run:
csv.Sniffer().sniff(f.readline())
which uses only the header row to determine the delimiter character. If you want to understand why the Sniffer heuristics fail for more data, there is no substitute for reading the csv.py library source code.

ASK SPARQL queries in rdflib

I'm trying to learn SPARQL and I'm using python's rdflib to train.
I've done a few tries, but any ASK query always seems to give me back a True result.
For instance, i tried the following:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import rdflib
mygraph=rdflib.Graph();
mygraph.parse('try.ttl',format='n3');
results=mygraph.query("""
ASK {?p1 a <http://false.com>}
""")
print bool(results)
The result is true, even if there is no subject of type false.com in 'try.ttl'.
Can anyone explain me why?
Thank you in advance for your help!
UPDATE: Reading the rdflib manual, I found out that results is of type list and (in my case) should contain a single boolean with the return value from the ask query.
I tried the following:
for x in results:
print x
And I got "None".
I'm guessing I don't use the query method in the right way.
The documentation doesn't actually says that it's of type list, but that you can iterate over it, or you can convert it to a boolean:
If the type is "ASK", iterating will yield a single bool (or
bool(result) will return the same bool)
This means that print bool(results), as you've done, should work. In fact, your code does work for me:
$ touch try.ttl
$ cat try.ttl # it's empty
$ cat test.py # same code
#!/usr/bin/python
# -*- coding: utf-8 -*-
import rdflib
mygraph=rdflib.Graph();
mygraph.parse('try.ttl',format='n3');
results=mygraph.query("""
ASK {?p1 a <http://false.com>}
""")
print bool(results)
$ ./test.py # the data is empty, so there's no match
False
If we add some data to the file that would make the query return true, we get true:
$ cat > try.ttl
<http://example.org> a <http://false.com> .
$ cat try.ttl
<http://example.org> a <http://false.com> .
$ ./test.py
True
Maybe you're using an older version of the library? Or a newer version and a bug was introduced? I'm using 4.0.1:
$ python
Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg_resources
>>> pkg_resources.get_distribution("rdflib").version
'4.0.1'

python not recognizing new created files

I have a python script that will create a text file and then will run a command on this newly created file.
The problem is that the command line is not recognizing the newly created file and I'm getting an error that the file is empty.
my code is something like this:
randomval is a function that will create random characters and return them as a string.
text_file = open("test.txt", "w")
text_file.write(randomval(20,10))
# do something with the `test.txt` file
but I'm getting an error that the file test.txt is empty.
Is there anyway to solve this?
This happens because unless you flush or close the file, the OS will not write any data to the disk. To make sure that the file is closed, use the with statement:
with open("test.txt", "w") as f:
f.write(randomval(20,10))
print('Whoa, at this point the file descriptor is automatically closed!')
Don't forget to close the file:
br#ymir:~$ python
Python 2.6.5 (r265:79063, Oct 1 2012, 22:04:36)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> file=open('foo.bar','w')
>>> file.write('42\n')
>>>
[2]+ Stopped python
br#ymir:~$ cat foo.bar
br#ymir:~$ fg
python
>>> file.close()
>>>
[2]+ Stopped python
br#ymir:~$ cat foo.bar
42
br#ymir:~$
You should, at least, flush the buffer before trying to do something with your new file (text_file.flush()). The best would be to close the file and reopen it when needed.
Do a f.close() and then open it again as text_file = open("test.txt", "r")
The stream to the file is still open!!!! Just try: text_file.close()

Is Python's seek() on OS X broken?

I'm trying to implement a simple method to read new lines from a log file each time the method is called.
I've looked at the various suggestions both on stackoverflow (e.g. here) and elsewhere for simulating "tail" functionality; most involve using readline() to read in new lines as they're appended to the file. It should be simple enough, but can't get it to work properly on OS X 10.6.4 with the included Python 2.6.1.
To get to the heart of the problem, I tried the following:
Open two terminal windows.
In one, create a text file "test.log" with three lines:
one
two
three
In the other, start python and execute the following code:
Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.stat('test.log')
posix.stat_result(st_mode=33188, st_ino=23465217, st_dev=234881025L, st_nlink=1, st_uid=666, st_gid=20, st_size=14, st_atime=1281782739, st_mtime=1281782738, st_ctime=1281782738)
>>> log = open('test.log')
>>> log.tell()
0
>>> log.seek(0,2)
>>> log.tell()
14
>>>
So we see with the tell() that seek(0,2) brought us to the end of the file as reported by os.stat(), byte 14.
In the first shell, add another two lines to "test.log" so that it looks like this:
one
two
three
four
five
Go back to the second shell, and execute the following code:
>>> os.stat('test.log')
posix.stat_result(st_mode=33188, st_ino=23465260, st_dev=234881025L, st_nlink=1, st_uid=666, st_gid=20, st_size=24, st_atime=1281783089, st_mtime=1281783088, st_ctime=1281783088)
>>> log.seek(0,2)
>>> log.tell()
14
>>>
Here we see from os.stat() that the file's size is now 24 bytes, but seeking to the end of the file somehow still points to byte 14?? I've tried the same on Ubuntu with Python 2.5 and it works as I expect. I tried with 2.5 on my Mac, but got the same results as with 2.6.
I must be missing something fundamental here. Any ideas?
How are you adding two more lines to the file?
Most text editors will go through operations a lot like this:
fd = open(filename, read)
file_data = read(fd)
close(fd)
/* you edit your file, and save it */
unlink(filename)
fd = open(filename, write, create)
write(fd, file_data)
The file is different. (Check it with ls -li; the inode number will change for almost every text editor.)
If you append to the log file using your shell's >> redirection, it'll work exactly as it should:
$ echo one >> test.log
$ echo two >> test.log
$ echo three >> test.log
$ ls -li test.log
671147 -rw-r--r-- 1 sarnold sarnold 14 2010-08-14 04:15 test.log
$ echo four >> test.log
$ ls -li test.log
671147 -rw-r--r-- 1 sarnold sarnold 19 2010-08-14 04:15 test.log
>>> log=open('test.log')
>>> log.tell()
0
>>> log.seek(0,2)
>>> log.tell()
19
$ echo five >> test.log
$ echo six >> test.log
>>> log.seek(0,2)
>>> log.tell()
28
Note that the tail(1) command has an -F command line option to handle the case where the file is changed, but a file by the same name exists. (Great for watching log files that might be periodically rotated.)
Short answer: no, your assumptions are.
Your text editor is creating a new file with the same name, not modifying the old file in place. You can see in your stat result that the st_ino is different. If you were to do os.fstat(log.fileno()), you'd get the old size and old st_ino.
If you want to check for this in your implementation of tail, periodically compare the st_ino of the stat and fstat results. If they differ, there's a new file with the same name.

Gzip and subprocess' stdout in python

I'm using python 2.6.4 and discovered that I can't use gzip with subprocess the way I might hope. This illustrates the problem:
May 17 18:05:36> python
Python 2.6.4 (r264:75706, Mar 10 2010, 14:41:19)
[GCC 4.1.2 20071124 (Red Hat 4.1.2-42)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import gzip
>>> import subprocess
>>> fh = gzip.open("tmp","wb")
>>> subprocess.Popen("echo HI", shell=True, stdout=fh).wait()
0
>>> fh.close()
>>>
[2]+ Stopped python
May 17 18:17:49> file tmp
tmp: data
May 17 18:17:53> less tmp
"tmp" may be a binary file. See it anyway?
May 17 18:17:58> zcat tmp
zcat: tmp: not in gzip format
Here's what it looks like inside less
HI
^_<8B>^H^Hh<C0><F1>K^B<FF>tmp^#^C^#^#^#^#^#^#^#^#^#
which looks like it put in the stdout as text and then put in an empty gzip file. Indeed, if I remove the "Hi\n", then I get this:
May 17 18:22:34> file tmp
tmp: gzip compressed data, was "tmp", last modified: Mon May 17 18:17:12 2010, max compression
What is going on here?
UPDATE:
This earlier question is asking the same thing: Can I use an opened gzip file with Popen in Python?
You can't use file-likes with subprocess, only real files. The fileno() method of GzipFile returns the FD of the underlying file, so that's what the echo redirects to. The GzipFile then closes, writing an empty gzip file.
just pipe that sucker
from subprocess import Popen,PIPE
GZ = Popen("gzip > outfile.gz",stdin=PIPE,shell=True)
P = Popen("echo HI",stdout=GZ.stdin,shell=True)
# these next three must be in order
P.wait()
GZ.stdin.close()
GZ.wait()
I'm not totally sure why this isn't working (perhaps the output redirection is not calling python's write, which is what gzip works with?) but this works:
>>> fh.write(subprocess.Popen("echo Hi", shell=True, stdout=subprocess.PIPE).stdout.read())
You don't need to use subprocess to write to the gzip.GzipFile. Instead, write to it like any other file-like object. The result is automagically gzipped!
import gzip
with gzip.open("tmp.gz", "wb") as fh:
fh.write('echo HI')

Categories

Resources