I'm trying to write a python script to generate a debian package.
I'm generating required folder structure in a temporary folder. In order to change uid and gid of /usr and subfolders to root I thought of using chroot.
However, on this line
os.chroot(tmpdir)
I get:
OSError: [Errno 1] Operation not permitted: '/tmp/tmpVnTqW7/myproj'
I've also tried this mini-tutorial with same results: http://www.tutorialspoint.com/python/os_chroot.htm
Why would that be?
Thanks
chroot() can be done only by root.
do one of these:
Run the script with sudo
Make the script setuid root, and do the setuid(geteuid()) equivalent python magic
I'm generating required folder structure in a temporary folder. In order to change uid and gid of /usr and subfolders to root I thought of using chroot.
I am not sure if you are on the right track. I don't know much about .deb packages, but in .rpm packages, you can define in the file list which file properties to assign to which files.
So you don't set them in the file system, but just tell the system what should happen.
As said, this counts for .rpm; I'm not sure if it is the same in .deb.
Instead of chrootting to the directory you should use fakeroot to execute dpkg-deb: fakeroot dpkg-deb -z8 -Zgzip --build myproj
Related
Nuitka is good at compiling Python to excutable binary.
But the compiled binary finds other resource files from original absolute path.
Thus, for moving to another computer requires to make the directory tree same as the original one.
For example, if I compile a project like this:
/home/me/myproj/
╠═ myprog.py
╚═ resource
╚═ foo.data
I should put the resulting binary and resource to the same location of another computer.
How to solve this problem?
My simpler spike is:
# /home/me/myproj/spike.py
import os
print(os.path.dirname(__file__))
And after compiling it, moving to any other location, I always got the result of /home/me/myproj.
I need a result like /another/path if I move compiled myproj.bin to /another/path.
Try using sys.argv[0] with os.path.abspath instead of __file__ .
For example:
abs_pth = os.path.abspath(sys.argv[0])
your_dir = os.path.dirname(abs_pth)
for val in abs_pth,your_dir:
print(val)
This will help you get the current path to the executable binary file, as well as work with directories located in the same folder.
https://nuitka.net/doc/user-manual.html#onefile-finding-files
There is a difference between sys.argv[0] and __file__ of the main
module for onefile more, that is caused by using a bootstrap to a
temporary location. The first one will be the original executable
path, where as the second one will be the temporary or permanent path
the bootstrap executable unpacks to. Data files will be in the later
location, your original environment files will be in the former
location.
# This will find a file near your onefile.exe
open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt"))
# This will find a file inside your onefile.exe
open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt"))
Another good function to resolve __file__ problem, it is to use --standalone flag, which create one main ".bin" file + other ".so" dependencies in one folder.
python -m nuitka --standalone program.py
https://nuitka.net/doc/user-manual.html#use-case-4-program-distribution
Assuming you created a whl of a proprietary project and would like to reuse it in another python project, how to indicate it via a relative path in a pip file without exposing whl online?
Although there is no direct description for this problem, from the documentation (https://pip.readthedocs.io/en/1.1/requirements.html) I have tried the following:
Indicate using -e file:
./folder/my-project-0.1.0-cp36-cp36m-linux_x86_64.whl#egg=my-project==0.1.0
got> NotADirectoryError: [Errno 20] Not a directory
Indicate using file:
./folder/my-project-0.1.0-cp36-cp36m-linux_x86_64.whl#egg=my-project==0.1.0
got> FileNotFoundError: [Errno 2] No such file or directory:
'/folder/my-project-0.1.0-cp36-cp36m-linux_x86_64.whl'
It seems to seek the file on the root folder instead of the relative one.
Indicate without file:
folder/my-project-0.1.0-cp36-cp36m-linux_x86_64.whl got> Invalid
requirement: 'folder/my-project-0.1.0-cp36-cp36m-linux_x86_64.whl'
It looks like a path. Does it exist ?
It appears that if I indicate the folder instead it will work.
But as this is not the case, does anyone know how to fix it?
numpy
pandas
file:./folder/my-project-0.1.0-cp36-cp36m-linux_x86_64.whl#egg=my-project==0.1.0
Pip install whl file using relative path with success!
I am working with a python package that I installed called bacpypes for communicating with building automation equipment, right in the very beginning going thru the pip install & git clone of the repository; the readthedocs calls out to:
Updating the INI File
Now that you know what these values are going to be, you can configure the BACnet portion of your workstation. Change into the samples directory that you checked out earlier, make a copy of the sample configuration file, and edit it for your site:
$ cd bacpypes/samples
$ cp BACpypes~.ini BACpypes.ini
The problem that I have (is not enough knowledge) is there isn't a sample configuration file that I can see in bacpypes/samples directory. Its only a .py files nothing with an .ini extension or name of BACpypes.ini
If I open up the samples directory in terminal and run cp BACpypes~.ini BACpypes.ini I get an error cp: cannot stat 'BACpypes~.ini': No such file or directory
Any tips help thank you...
There's a sample .ini in the documentation, a couple of paragraphs after the commands you copied. It looks like this
[BACpypes]
objectName: Betelgeuse
address: 192.168.1.2/24
objectIdentifier: 599
maxApduLengthAccepted: 1024
segmentationSupported: segmentedBoth
maxSegmentsAccepted: 1024
vendorIdentifier: 15
foreignPort: 0
foreignBBMD: 128.253.109.254
foreignTTL: 30
I'm not sure why you couldn't copy BACpypes~.ini. I know tilda could be expanded by your shell so you could try to escape it with
cp BACpypes\~.ini BACpypes.ini
Though I assume it isn't needed now that you have a default configuration file.
I have a directory structure with many log files.
Example:
root/feature1/pre/a.log<br>
root/feature1/pre/b.log<br>
root/feature1/post/c.log<br>
root/feature1/post/d.og<br>
root/feature2/pre/e.log<br>
root/feature2/pre/f.log<br>
root/feature2/post/g.log<br>
root/feature2/post/h.log
I want to archive few of the log files with the condition that log files are older than 2 months. I could archive the log files with the given condition but couldn't maintain directory inside tar file.
I need :
root/archive.tar.gz
Where archive.tar.gz contains
feature1/pre/a.log
feature1/post/d.log
feature2/pre/e.log
feature2/post/g.log
feature2/post/h.log
Here, a.log, d.log, e.log, g.log, h.log files are the ones older than 2 months.
This is more of a Linux problem than Python. I suggest using the find command with file name and file time options. Pass those names into the tar command you're using, something like
tar -czf archive `find /root -name feature*.log -ctime +60`
Test this on your command line; when it works as you want, then use Python's os package to execute it from your Python script.
Does that get you moving?
I'm making a compress script for my text editor, and it's all working up to the part where it needs to make the file Run. Inside of Run is just this code: python ./App.pyc. When I run the program by double-clicking on it in Finder, it says that it can't open file './App.pyc' [Errno 2] No such file or directory within Terminal.
And if I run it through Terminal after I've cd'd to the directory Run and App.pyc are in, it works. I'm assuming this is because we aren't in the right directory.
My question is, how can I make sure Run is being ran in the right directory? If I put cd in it, it'll work, but then if somebody moves the folder elsewhere it won't work anymore.
#!/usr/bin/python
### Compresser script.
# Compress files.
import App
import Colors
# Import modules
import os
# Clear the folder to put the compressed
# files in (if it exists).
try:
os.system('rm -rf BasicEdit\ Compressed')
except:
pass
# Remake the folder to put compressed files in.
os.system('mkdir BasicEdit\ Compressed')
# Move the compiled files into the BasicEdit
# Compressed folder.
os.system('mv App.pyc BasicEdit\ Compressed/')
os.system('mv Colors.pyc BasicEdit\ Compressed/')
# Create contents of run file.
run_file_contents = "python ./App.pyc\n"
# Write run file.
run_file = open("./BasicEdit Compressed/Run", 'w')
run_file.write(run_file_contents)
# Give permissions of run file to anybody.
os.system('chmod a+x ./BasicEdit\ Compressed/Run')
# Finally compress BasicEdit, and remove the old
# folder for BasicEdit Compressed.
os.system('zip -9r BasicEdit.zip BasicEdit\ Compressed')
os.system('rm -rf BasicEdit\ Compressed')
(PS, what's [Errno 1]? I've never seen it before.)
The Python script's current working directory can be modified with the os.chdir() call, after which references to . will be correct.
If you want to find the location of the source file currently being run rather than hardcoding a directory, you can use:
os.chdir(os.path.dirname(__file__))
The bash equivalent to this logic is:
cd "${BASH_SOURCE%/*}" || {
echo "Unable to change directory to ${BASH_SOURCE%/*}" >&2
exit 1
}
See BashFAQ #28 for more details and caveats.
As developed above together with #William Purcell, you have to retrieve the absolute path by os.pwd() and then use the absolute path for the python call.
I withdraw my proposal and go with #Charles Duffy's answer. However, I don't delete my attempt as the comments seem to be useful to others!